1

다음 두 줄의 출력은 NSString의 stringWithFormat 문이 숫자를 항상 반올림하지 않음을 보여줍니다. 그것은 정확하게 0.75에서 0.8로 반올림하는 것 같습니다. 그러나 0.25에서 0.25로 반올림됩니다. 여기에 코드가 있습니다.NSString 클래스가 숫자 서식을 지정할 때 일관성없는 이유는 무엇입니까?

NSString *sRoundedScore = [NSString stringWithFormat:@"%.1f", fScore]; 
    NSLog(@"\r\n score before rounding: %f, rounded score: %@", fScore, sRoundedScore); 

fScore 0.25로 할당 될 때, 출력은 :

score before rounding: 0.250000, rounded score: 0.2 

fScore 0.75로 할당 될 때, 출력은 :

score before rounding: 0.750000, rounded score: 0.8 

제가 사용하기 시작했다 이 NSNumberFormatter 일관되게 최대 얻을 수 있습니다. 왜 stringWithFormat이 결과에서이 변형을 생성합니까?

답변

3

이 답변은 "printf와"기능

은행 반올림로 돌아갑니다 :

그것은 중요이 더 당신이 부동 소수점 정수에 소수의 장소를 표시 할 것을 주장입니다 알고.

하나의 소수점을 나타 내기 때문에 두 번째 십진수를 검사하여 어디에서 반올림할지 결정합니다. % .f format'er의 반올림 논리는 다음과 같이 작동합니다. 직접 앞자리의 숫자가 4보다 작 으면 앞면의 숫자가 4 이상이고 5 위 이상인 경우 5 줄 넘김. 이것의

이유 : http://linuxgazette.net/144/misc/lg/a_question_of_rounding_in_issue_143.html :. 은행 반올림 "또는"라운드 심지어 "이 같은 다른 C 라이브러리보다 더 정확하기"는 GNU C 라이브러리의 경우는()의 printf에서 사용하는 반올림 규칙은 " C99 사양에 따르면 소수로 변환하려면 현재 선택한 IEEE 반올림 모드 (기본 은행 반올림)를 사용해야합니다. "

이 대답에서 발견 : printf rounding behavior for doubles

당신이 라운드 인라인 위의 트릭을 할 약간의 수학와 C 함수 라운드()를 사용일반적인 라운딩을하고 싶지 또는 당신이 할 수있는 경우 귀하가 진술 한대로 NSNumberFormatter을 사용하십시오.

Rounding numbers in Objective-C

+0

그렇다면 제안한대로 0.75를 반올림하면 왜 0.25를 내립니다. 그것이 내가 여기서 묻고있는 질문이다. 왜 어떤 경우에는 위로, 다른면에서는 아래로. – Alyoshak

+0

.25 .2가 .5 (또는 .45)보다 작 으면 .25이므로 반올림됩니다 .55는 .6으로 반올림됩니다. 그러나 .5 이하인 경우 .26을 반올림하면 .26을 반올림합니다. 왜 그렇게하는지에 대한 저수준 논리가있을 것이라고 확신하지만, 그것이 그렇게한다는 것을 아는 것이 더 중요합니다. –

+0

Thx Ben. 나는 그것이 그것을하는 이유보다 이것을하는 것을 아는 것이 더 중요하다는 데 동의하지 않는다. 귀하의 의견이 도움이되기 때문에, 나는 단순히 행동의 예가 아니라 행동의 설명을 얻기를 희망합니다. 소수 자릿수로 서식을 지정하면 결과가 임의적으로 보입니다. 데이비드의 대답은 유망하지만 아직 어떤 일이 일어나고 있는지, 구현시 0.25을 0.2499999999로 저장하지만 0.75를 0.74999999로 저장하지 않는지 아직 확인할 수 없습니다. – Alyoshak

1

루트 문제는 0.25를 볼 때, 숫자가 실제로 더 0.2499999999999 같은 것입니다. 원하는 라운딩을 얻기위한 몇 가지 표준 기술이 있습니다. 이 특정한 경우에, 당신은 다음, 100.0f로 플로트를 곱 lroundf 사용하고 긴 인쇄 할 수 있습니다 통합에 나는 미국 통화를 사용할 때마다

float foo = 0.25f; 
NSLog(@"First %f", foo); 
NSLog(@"Round %.1f", foo); 
foo += 0.0000001; 
NSLog(@"Second %f", foo); 
NSLog(@"Round %.1f", foo); 
//2013-07-18 15:36:09.021 EmailAddressFinder[12618:303] First 0.250000 
//2013-07-18 15:36:09.022 EmailAddressFinder[12618:303] First 0.2 
//2013-07-18 15:36:09.022 EmailAddressFinder[12618:303] Second 0.250000 
//2013-07-18 15:36:09.022 EmailAddressFinder[12618:303] Second 0.3 

foo = 0.25f; 
foo *=100; 

long l = lroundf(foo); 
NSLog(@"l=%ld", l); 
NSLog(@"0.%0.2ld", l); // .2=="print two places", 0=="add a leading 0 if needed" 
//2013-07-18 15:37:24.424 EmailAddressFinder[13474:303] 0.25 

당신은 범위 등을 위해 조정해야합니다, 나는 항상 곁에 라운드 센트를이 방법으로 사용하고 작은 방법을 사용하여 나에게 dollar 센트 문자열을 다시 센트에서,이 같은 기술을 사용합니다.

EDIT : 답을 얻은 것을 봅니다. printf의 동작을 사용하여 사용자가보고 싶은 것을 결정하는 사람은 어느 시점에서 문제가 발생할 것입니다. 너가 확실히 알고있는 무언가로 수를 cooerce 하거든 너는 강력하고 이식 가능한 부호를있을 것이다.

+0

printf와 함께 사용했던 서식 스타일을 사용하려고했지만 Xcode는 그것을 좋아하지 않습니다. (저는 .m 파일이고 .mm이 아닙니다.) 컴파일되지 않습니다. 그것으로 더 많은 것을 망칠 것입니다,하지만이 질문은 NSString 클래스의 stringWithFormat 메서드와 관련이 있습니다. 그래서 당신이 그걸로 무엇을 의미하는지 보여 줄 수 있습니다. 당신은 0.25가 실제로 0.249999999로 저장된다는 것을 말하고 있습니다. 이것은 동작의 일부를 확실히 설명 할 것입니다. 그러나 0.75가 반올림 된 이유는 설명하지 않습니다. 0.25와 0.75 둘 다 실제로 저장되는 것을 볼 수 있다면 실제로 깨달을 것입니다. – Alyoshak

+0

부동 소수점은 복잡한 주제입니다. 값은 밑이 10인데 밑이 두인데 두 부분으로 나뉘어져 있고 숫자로 변환하는 것은 복잡한 결정을 많이 포함합니다. –

+0

의미가 있습니다. 이치에 맞지 않는 이유는 번역 프로세스가 한 가지 경우에는 가치가 약간 저하되지만 다른 분야에서는 약간 증가하는 이유입니다. 내 손에 버그가있을 수 있다고 생각했는데, 아마도보고해야 할 것이지만, 은행가의 반올림 이론이 제시 될 때까지 그럴듯한 설명이 없었습니다. – Alyoshak