Microsoft MVP성태의 닷넷 이야기
글쓴 사람
spowner (spowner at naver.com)
홈페이지
첨부 파일
 
문제 : 특정 범위의 값을 다른 값으로 치환하는 행위를 빠르게 처리 하여야 한다
전제 : 값형은 double, 값의 범위에 대한 목록 동적으로 많이 등록할 수 있음
설명 :

가령, 0 ~ 1000 범위의 값일 경우, 입력 값이 1000일 경우 출력값은 980이 됩니다. 즉, 0 ~ 1000 범위 안의 값일 경우 율이 980 / 1000 이므로 입력값에 0.98을 곱하는 식입니다
그런데 이 범위 레인지는 특정하지 않고 리스트로 무한대 등록이 가능하다고 가정합니다.
즉,

0 ~ 1000 => 980, out = input * 0.98
1001 ~ 2000 => 1900, out = input * xx
2001 ~ 4000 => 3800, out =...
4001 ~ 8000 => 7600,
8001 ~ 10000 => 9400,
...

단순무식한 방법으로는 범위 시작과, 범위 종료를 리스트로 관리하고, 앞으로 검색, 뒤로 검색하여 범위를 찾고 율을 계산해서 사용하는 것인데,
이 방식은 쉽지만 호출횟수가 많으면 많을수록 (가령, 1ms 간격으로) 굉장한 성능하락이 예상되는데요,

좀 더 효율적인 방법이 무엇이 있을까요??




donaricano-btn



[최초 등록일: ]
[최종 수정일: 2/6/2017]


비밀번호

댓글 쓴 사람
 



2017-02-06 01시01분
음... 문제를 좀 더 설명해 주셔야 할 것 같습니다. 잘 이해가 안되는 군요. ^^; 그러니까, 리스트에 0,1,2,...,1000의 값이 들어 있는데 입력 값이 1,000이면 980을 출력한다는 건가요? 아니면, 리스트 중간에 값이 비어 있을 수 있다는 건가요?
정성태
2017-02-07 03시25분
[spowner] 죄송합니다. 일하면서 쓰느라.. (라고 변명하면서 글을 잘 못씁니다)
중간 비어있는 것 맞고요, 제가 고민하는 것은 (min, max)=rate 로 이루어진 아이템이 있고 이 아이템이 복수개일 때, 특정 값을 입력하면 min >= value && max < value 인 rate를 찾아서 output에 value*rate(또는 rate)를 반환해야 합니다
제가 선택한 방법은 목록에 min과 max를 찾아 거기에 부여된 rate를 잡아내는 건데, 목록 전체 검사를 해야 합니다. Dictionary의 경우 일대일 매칭인 반면, 제가 원하는 것은 범위 매칭인 샘이죠

[손님]
2017-02-07 03시36분
[spowner] 범위는 중첩될 수는 있으나, 문제를 쉽게 해결하기 위해 중첩은 배제하는 것으로 합니다... 답을 주세요~ 라고 강요하는 것은 아닙니다 T_T 다른 아이디어가 궁금해요
[손님]
2017-02-07 04시06분
[ryujh] 안녕하세요.

아래는 메모를 붙인 것이니 확인 바랍니다.

원래 제공하는 것(문법, 라이브러리 등)을 있는 그대로 활용하는 것이 가장 좋다는 생각입니다.

----------
min 의 sortedlist key (0, 1001, 2001, 4001, ... ) value (0.98, xx, ...)
max 의 sortedlist key (1000, 2000, 4000, 8000, ... ) value (0.98, xx, ...)

input(100) 를 min 에 add key 하면 (0, 100, 1001) 이고 input보다 작은 key의 value 를 구하여 0.98 input과 곱한다.
input(100) 를 max 에 add key 하면 (100, 1000) 이고 input보다 큰 key의 value 를 구하여 0.98 input과 곱한다.

동적으로 등록하기 때문에 sortedlist(sorteddictionary) 로 정렬하는 방법 이외에 있을지 모르겠음.

if/else, switch 문으로는 되지 않을 것임.
---------




[손님]
2017-02-07 07시05분
[spowner] @ryujh님 감사합니다. 님 덕분에 아이디어가 떠올랐어요. 제가 알기로 참조형 인스턴스의 Directory류 탐색의 키는 HashCode를 재정의 함으로서 가공할 수 있는것으로 아는데, 아이템의 HashCode를 min+max로 고유하게 만든 다음, 입력값으로 해당 것을 찾도록 하면 되겠네요... 머리속으로는 정리됐는데, 구현해봐야겠습니다
[손님]
2017-02-07 07시09분
[spowner] 아아.. 생각처럼 안되는군요 T_T
[손님]
2017-02-07 08시21분
[spowner] 이렇게 해결했습니다. 생각을 해보면 답은 가까운데 있는데, 어렵게 생각했네요.. 참고하시라고 소스코드 공개합니다

-----------------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp8
{
    class Program
    {
        static void Main(string[] args)
        {
            // 등록된 범위는 중복되지 않다고 가정
            var list = new List<Item>
            {
                new Item { Min = 0, Max = 1000, Rate = 0.9d },
                new Item { Min = 1001, Max = 2000, Rate = 1.1d },
                new Item { Min = 2001, Max = 3000, Rate = 1.2d },
                new Item { Min = 3001, Max = 4000, Rate = 1.2d },
                new Item { Min = 4001, Max = 5000, Rate = 1.0d }
            };

            // 목록은 항상 정렬되었다고 가정
            list.Sort((x, y) =>
            {
                return x.Max.CompareTo(y.Min);
            });

            // 목록 출력
            foreach (var i in list)
            {
                Console.WriteLine(i);
            }

            Console.WriteLine();

            // 정렬되어 있으므로 이진검색 가능
            var value = 4500;
            var item = new Item(value);
            var index = list.BinarySearch(item, item);

            var rate = list[index].Rate;

            Console.WriteLine($"{value} => {rate}");
        }
    }

    public class Item : IComparer<Item>
    {
        public double Min { get; set; }
        public double Max { get; set; }
        public double Rate { get; set; }

        public Item()
        {
        }

        public Item(double value)
        {
            Max = value;
        }

        public override string ToString()
        {
            return $"{Min} ~ {Max} : {Rate}";
        }

        public int Compare(Item x, Item y)
        {
            var value = y.Max;

            if (value >= x.Min && value <= x.Max)
                return 0;
            else if (value < x.Min)
                return 1;
            else // else if (x.Max > value)
                return -1;
        }
    }
}

[손님]

[1]  2  3  4  5  6  7  8  9  10  11  12  13  14  15  ...
NoWriterDateCnt.TitleFile(s)
5566민성10/26/202163Linq에 관해서 [1]
5565password510/25/2021101wpf에서 Cefsharp를 AnyCPU로 작업 했는데 실행이 되지 않습니다. [4]
5564초보10/21/2021106오버라이드 관련 질문드립니다 [2]
5562서지훈10/20/2021151win32 api 문의 드립니다. (EnableMenuItem) [5]
5561Edun10/15/2021255도와주세요!! 팝업 띄우는 더블클릭 이벤트!! 부탁드립니다 ㅠㅠ [4]파일 다운로드1
5560Edun10/13/2021274C#초보자 개념이해 도와주세요!! [4]
5559최가운10/5/2021291C# debugging 중에 Thread Pool Worker들이 사라지는데요 [3]
5558옥코드9/29/2021260안녕하세요! EntityFramework Linq 질문 드리겠습니다. [4]
5557임기성9/16/2021387웹 사이트(IIS)가 오류로 인하여 빈번하게 죽는 이슈 문의 [1]
5556hjlee9/13/2021202visual studio 설치 없이 csi.exe (C# interactive) tool을 설치할 수 있을까요? [2]
5555이성열9/2/2021219C# 런타임(Reflection)에서 소스코드에 입력한 함수설명(Summary)을 가져올 수 있을까요? [3]
5554농상9/2/2021439enum 원소값이 중복인 경우 출력 [4]
5553shdtkd378/31/2021394제너릭을 new로 할당했는데 null인 경우가 존재하나요? [1]
5552hjshimdm8/30/2021256C# 폼 - 마우스가 다른 버튼 위를 움직일 때도 폼의 페인트핸들러가 호출되는 것이 맞나요? [2]
5551하나다라마8/27/2021289뽀모도로 타이머 개선사항 [1]
5550하영8/27/2021762SqlDataReader 관련 질문입니다. [8]
5549책 감사합니다8/23/2021758C# 9.0 책 오타 [1]
5548Dev8/23/2021730String의 IndexOfAny 함수 질문 [3]
5547민성8/20/2021684WPF Radio 버튼을 GroupName으로 읽어와서 비교하기 [1]
5546DeveloperST8/19/2021801C++ C# API 연동 관련 [1]
5545영귤8/18/2021341C# 14.3장 예제에서 반환 값의 값 복사 부하가 어디서 발생하는 것인가요? [4]
5544이상호8/18/2021261C# Graphics 객체 저장 가능 여부 [2]
5543정형지8/18/2021270c# outofmemoryexception [3]
5542영귤8/11/2021317C#9.0 886쪽 오류 발생 안 해요 [2]
5541서지훈8/11/2021470C# 응용프로그램(Winform)의 비정상 종료(Exit Code) [2]
[1]  2  3  4  5  6  7  8  9  10  11  12  13  14  15  ...