문제

첫 번째 앱을 코딩하기 시작하면서 NSNUMBER를 두 번 생각하지 않고 돈 가치에 NSNUMBER를 사용했습니다. 그런 다음 C 유형이 내 가치를 다루기에 충분하다고 생각했습니다. 그러나 나는 iPhone SDK 포럼에서 우수한 반올림 기능 때문에 nsdecimalnumber를 사용하도록 권고 받았다.

기질에 의해 수학자가 아닌, 나는 만티 사/지수 패러다임이 과잉 일 수 있다고 생각했다. 그럼에도 불구하고, Googlin '주변에서 나는 코코아의 돈/통화에 대한 대부분의 이야기가 nsdecimalnumber로 언급되었다는 것을 깨달았습니다.

내가 작업중 인 앱은 국제화 될 것이므로, 금액을 계산하는 옵션은 실제로 실행 가능하지 않습니다. 금전적 구조는 사용 된 로케일에 크게 의존하기 때문입니다.

나는 NSDECIMALNUMBER와 함께 가야한다고 90% 확신하지만 웹에서 명백한 대답을 찾지 못했기 때문에 ( "돈을 다루면 NSDECIMALNUMBER를 사용하십시오!") 나는 여기서 물어볼 것이라고 생각했습니다. 어쩌면 대답은 대부분 분명하지만 앱의 대규모 리팩토링을 시작하기 전에 확신하고 싶습니다.

나를 설득하십시오 :)

도움이 되었습니까?

해결책

Marcus Zarra는 이것에 대해 매우 분명한 입장을 가지고 있습니다. "통화를 전혀 다루고 있다면 nsdecimalNumber를 사용해야합니다." 그의 기사는 나에게 nsdecimalnumber를 조사하도록 영감을 주었고, 나는 그것에 깊은 인상을 받았습니다. Base -10 수학을 다룰 때 IEEE 부동 소수점 오류는 한동안 나를 자극했습니다 (1 * (0.5-0.4-0.1) = -0.0000000000000000002776) 및 NSDECIMALNUMBER는 그들과 멀리합니다.

nsdecimalNumber는 이진 부동물 포인트 정밀도의 또 다른 몇 자리를 추가 할뿐 아니라 실제로베이스 -10 수학을합니다. 위의 예에 표시된 오류와 같은 오류가 제거됩니다.

이제 저는 상징적 수학 응용 프로그램을 작성하고 있습니다. 따라서 30+ 십진수 정밀도에 대한 욕구와 이상한 부동 소수점 오류는 예외 일 수 있지만 볼 가치가 있다고 생각합니다. 운영은 단순한 var = 1 + 2 스타일 수학보다 약간 어색하지만 여전히 관리 가능합니다. 수학 작업 중에 모든 종류의 인스턴스를 할당하는 것이 걱정된다면, nsdecimal은 nsdecimalnumber와 동일한 C 구조물이며 정확히 동일한 수학 작업을 수행하기위한 C 함수가 있습니다. 내 경험상, 이것들은 가장 까다로운 응용 프로그램 (3,344,593 개의 추가/S, MacBook Air의 254,017 부서, 281,555 개의 추가/S, iPhone에서 12,027 개의 부서/s)에게 충분히 빠릅니다.

추가 보너스로 NSDECIMALNUMBER의 DescriptionWithLocale : Method는 올바른 소수점 분리기를 포함하여 국소화 된 버전의 문자열을 제공합니다. InitwithString : Locale : Method.

다른 팁

예. 당신은 사용해야합니다

NSDECIMALNUMBER 그리고

~ 아니다 더블 또는 뜨다 iOS에서 통화를 처리 할 때.

왜 그런 겁니까??

우리는 같은 것을 얻고 싶지 않기 때문입니다 $9.9999999998 대신에 $10

어떻게 되는가 ??

수레와 복식은 근사치입니다. 그들은 항상 반올림 오류가 있습니다. 형식 컴퓨터는 소수점을 저장하는 데 사용하면이 루딩 오류가 발생합니다. 자세한 내용이 필요한 경우 읽으십시오

http://floating-point-gui.de/

Apple Docs에 따르면

NSDECIMALNUMBER는 NSNUMBER의 불변의 서브 클래스이며 Base-10 산술을 수행하기위한 객체 지향 래퍼를 제공합니다. 인스턴스는 Mantissa x 10^지수로 표현 될 수있는 모든 숫자를 나타낼 수 있으며 Mantissa는 최대 38 자리 길이의 소수 정수이며 지수는 –128에서 127의 정수입니다.

따라서 NSDECIMALNUMBER는 통화를 다루기 위해 권장됩니다.

(다른 답변에 대한 나의 의견에서 적응했다.)

예, 당신은해야합니다. 필연적 인 동전 수는 반 센트를 나타내지 않아도됩니다. 이 경우 반 센트를 계산하도록 변경할 수 있지만, 1/4 센트 또는 8 센트를 대표해야한다면 어떻게해야합니까?

유일한 적절한 솔루션은 NSDECIMALNUMBER (또는 그와 비슷한 것)로, 문제를 10^-128 ¢ (즉,, 즉,
0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000001¢).

(또 다른 방법은 임의의 예비 산술이지만, 이는와 같은 별도의 라이브러리가 필요합니다. GNU MP Bignum 라이브러리. GMP는 LGPL 아래에 있습니다. 나는 그 라이브러리를 사용한 적이없고 그것이 어떻게 작동하는지 정확히 알지 못해서 그것이 당신에게 얼마나 잘 작동하는지 말할 수 없었습니다.)

편집 : 분명히, 적어도 한 사람인 브래드 라슨 (Brad Larson)은이 답변의 어딘가에 이진 부유 식 점에 대해 이야기하고 있습니다. 난 아니에요.

더 나은 질문은 언제라도해야한다는 것입니다 ~ 아니다 돈을 다루기 위해 nsdecimalnumber를 사용하십시오. 그 질문에 대한 짧은 대답은 NSDECIMALNUMBER의 성능 오버 헤드를 견딜 수없고 정밀도의 몇 자리 이상을 다루지 않기 때문에 작은 반올림 오류에 신경 쓰지 않는다는 것입니다. 더 짧은 대답은 당신이해야합니다 언제나 돈을 다룰 때 nsdecimalnumber를 사용하십시오.

정수를 사용하여 센트 수를 나타내고 프레젠테이션을 위해 100으로 나누는 것이 편리하다는 것을 알았습니다. 전체 문제를 피하십시오.

비자, 마스터 카드 및 기타는 금액을 통과하는 동안 정수 값을 사용하고 있습니다. 통화 지수에 따라 올바르게 Amouts를 구문 분석하는 것은 발신자 및 리시버에게 달려 있습니다 (NUM-는 화폐의 지수 인 10^num을 나누거나 곱합니다). 통화가 다르면 지수가 다릅니다. 일반적으로 2 (따라서 우리는 100을 나누고 곱하기)이지만 일부 통화에는 지수 = 0 (VND 등), 또는 = 3이 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top