NSNumberFormatter со значащими цифрами форматов 0,0 неправильно

У меня есть NSNumberFormatter, настроенный для форматирования с использованием значащих цифр, поэтому он должен отображать только столько десятичных цифр, сколько необходимо для правильного отображения значения.

Когда он используется для форматирования 7.0, он работает точно так, как ожидалось, и производит @"7", но когда он используется для форматирования 0.0, форматтер создает @"0.0" вместо @"0", как можно было бы ожидать.

NSNumberFormatter *doubleValF = [[NSNumberFormatter alloc] init];
[doubleValF setNumberStyle:NSNumberFormatterDecimalStyle];
[doubleValF setRoundingMode:NSNumberFormatterRoundHalfUp];

doubleValF.maximumFractionDigits = 9;
doubleValF.minimumFractionDigits = 0;
doubleValF.minimumSignificantDigits = 0;
doubleValF.maximumSignificantDigits = 30;
[doubleValF setUsesSignificantDigits:YES];

double value1 = 0.0;
NSString *value1String = [doubleValF stringFromNumber:[NSNumber numberWithDouble:value1]];

double value2 = 7.0;
NSString *value2String = [doubleValF stringFromNumber:[NSNumber numberWithDouble:value2]];

NSLog(@"value1=%@", value1String);
NSLog(@"value2=%@", value2String);

Когда я запускаю этот код, я получаю следующий результат:

2012-12-15 15:57:03.425 StackOverflowTests[41701:11303] value1=0.0
2012-12-15 15:57:03.426 StackOverflowTests[41701:11303] value2=7

person Kenny Wyland    schedule 16.12.2012    source источник


Ответы (3)


Следуя сообщению Дэвида LaMacchia, просто проверьте нулевое значение и установите режим sig fig:

if(fabs(value) < 1e-6) {
    self.numberLabelFormatter.usesSignificantDigits = NO;
}
else {
    self.numberLabelFormatter.usesSignificantDigits = YES;
}
self.numberLabel.text = [self.numberLabelFormatter stringFromNumber:[NSNumber numberWithDouble:value]];

Возможно, это не правильный метод, но он работает для меня.

person danomatika    schedule 07.03.2013
comment
Всякий раз, когда вы видите значение с плавающей запятой и == вместе, у вас в голове должна сработать сирена, потому что вы не должны доверять тому, что переменная ИМЕННО 0,0 во всем значении. - person Kenny Wyland; 08.03.2013
comment
Конечно. Но мне не нужна большая точность, и все работает нормально. В этом случае я не волнуюсь. - person danomatika; 09.03.2013
comment
Когда дело доходит до вычислений, дело не в точности самого числа, я имею в виду, будет ли выражение if () оцениваться как истинное. У вас может быть число 0,00000001, которое, по вашему мнению, должно быть 0, но оно будет оцениваться как false по сравнению с 0,0, и ваше предложение else будет срабатывать вместо if. - person Kenny Wyland; 09.03.2013
comment
Ваш код, скорее всего, будет работать каждый раз, когда вы его тестируете, но возможен произвольный сбой. Вам следует подумать об изменении вашего оператора if () на что-то вроде if (fabs(value) < 1e-6), которое будет оцениваться как истинное, пока значение находится в диапазоне от -0,000001 до 0,000001. - person Kenny Wyland; 09.03.2013
comment
@KennyWyland Хороший совет. Точное значение для проверки - FLT_EPSILON для числа с плавающей запятой. - person Echelon; 29.01.2015

Проблема связана с тем, что вы установили usesSignificantDigits на YES. Я считаю, что конечная цифра в 0.0 считается значимой.

Здесь есть хорошее обсуждение связанной проблемы: https://stackoverflow.com/a/13110633/1435955

person David LaMacchia    schedule 16.12.2012
comment
Я прочитал связанную статью и не верю, что она решает мою конкретную проблему, заключающуюся в том, что .0 включается, только если значение равно 0. В случае 7.0 он не включается. - person Kenny Wyland; 16.12.2012

Попробуйте установить для свойства zeroSymbol средства форматирования чисел значение @ "0".

doubleValF.zeroSymbol = @"0"; 
person ninjaproger    schedule 13.04.2015