Подтвердить что ты не робот

Как печатать двойной с полной точностью на iOS?

Тестовый пример:

NSLog(@"%f", M_PI);
NSLog(@"%@", [NSString stringWithFormat:@"%f", M_PI]);
NSLog(@"%@", [NSNumber numberWithDouble:M_PI]);

Результаты:

3.141593
3,141593
3,141592653589793

Выводы:

1) Печать через NSLog() или [NSString stringWithFormat] обеспечивает очень низкую точность...

2) Печать с помощью [NSNumber numberWithDouble] обеспечивает лучшую точность...

Я бы ожидал получить результат намного ближе к исходному значению: 3.14159265358979323846264338327950288 (как определено в math.h)

Любые подсказки?

4b9b3361

Ответ 1

Первые две строки округляются до 6 десятичных знаков, потому что длина округления по умолчанию для printf, унаследованная от C.

Третья строка отображает данные с максимальной полезной точностью - число с плавающей запятой IEEE 754 с 64-разрядными числами имеет чуть меньше 16 десятичных цифр точности, поэтому все эти цифры литерала в math.h бессмысленны (возможно, они могут как будущая защита от возможного будущего переопределения в формате с большей точностью).

Ответ 2

Попробуйте следующее:

NSLog(@"%.20f", M_PI);

Ответ 3

Возможно, немного поздно, как ответ, но кто-то может наткнуться на эти проблемы:

Вы должны использовать длинный двойной с максимальным форматированием 20 цифр @. 20Lg. Длинные удваиваются 80-битные плавающие точки, поэтому вы не получите более высокую точность, чем это. Имейте в виду также, что с XCode 4.3.2 константы не имеют длинных двойных обозначений, даже если многие цифры указывают на удвоение двойника; -)

NSLog(@"%.21g", M_PI);

// with cast because M_PI is not defined as long double
NSLog(@"%.21Lg", (long double)M_PI);

// with corrected long double representation (#.####L):
//                                   v from here on overhead 
NSLog(@"%.21Lg", 3.14159265358979323846264338327950288L);

// alternative for creating PI
NSLog(@"%.21Lg", asinl(1.0)*2.0);
// and a funny test case:
NSLog(@"%.21Lg", asinl(1.0)*2.0 - M_PI); // on second thought, not that funny: should be 0.0

результаты:

p[5528:f803] 3.141592653589793116   (actually 16 digits standard double precision)
p[5528:f803] 3.141592653589793116
p[5528:f803] 3.14159265358979323851
p[5528:f803] 3.14159265358979323851
p[5575:f803] 1.22514845490862001043e-16 (should have been 0.0)

Ответ 4

NSLog(@"%@", [NSDecimalNumber numberWithDouble:M_PI]); 

немного больше точности