안녕하세요, 최근 거래소 api들을 사용하다가 부동소수점 관련해서 문제가 발생하는 것을 발견해서 해결방법에 대해 질문좀 드리려고합니다.
api응답은 string으로 주고있는데, 저는 이것을 받아서 더하거나 곱하는 등의 연산을 해야해서
형변환을 해야합니다. 이때 Convert.ToDouble을 사용해서 double로 형변환을 해주고 있었는데요, 문제는 형변환을 하면서 부동소수점으로 오차가 미세하게 발생해서 api 요청에 실패를 하고 있다는 것입니다…
그래서 해결방법을 찾아보고 고민해봤는데 일단 크게 두가지 방법을 찾아봤습니다.
Decimal 타입 사용
정밀도를 더 높혀서 오차범위를 줄이기
형변환 한 값에 2를 곱한 후 다시 2로 나누기
더 큰값을 만들고 나눔으로써 오차범위를 줄이기
이 두가지 방법중에 어떤게 괜찮을까요? 혹은 다른 괜찮은 방법이 있다면 알려주시면 감사하겠습니다 !
기본적으로 반환 값은 최대 17자리가 내부적으로 유지 관리되지만 15자리의 정밀도만 포함합니다. 이 instance 값이 15자리보다 크면 예상 숫자 대신 또는 NegativeInfinitySymbol 를 반환 PositiveInfinitySymbol 합니다ToString. 더 정밀도를 필요로 하는 경우 항상 17자리의 정밀도를 반환하는 “G17” 형식 사양 또는 숫자가 해당 정밀도로 표현될 수 있는 경우 15자리를 반환하는 “R” 또는 숫자가 최대 정밀도로만 표현될 수 있는 경우 17자리를 지정 format 합니다.
번역이 조금 이상하네요
By default, the return value only contains 15 digits of precision although a maximum of 17 digits is maintained internally. If the value of this instance has greater than 15 digits, ToString returns PositiveInfinitySymbol or NegativeInfinitySymbol instead of the expected number. If you require more precision, specify format with the “G17” format specification, which always returns 17 digits of precision, or “R”, which returns 15 digits if the number can be represented with that precision or 17 digits if the number can only be represented with maximum precision.
따라서 ToString("G17")으로 호출해 보시면 잘림 없이 원본 값을 유지할 수 있을 듯 합니다.
거래소API를 다루시는데 비트코인 소스는 한번도 보신적이 없으신거 같네요. 비트코인 소스에 정답이 있습니다. 비트코인은 내부적으로는 64비트 정수형으로 처리하고 단지 표시만 소수점인 것처럼 보이게 하고 있으며 알트코인이나 거래소 코드들도 다 마찬가지입니다. long형을 쓰시는게 "정답"입니다