Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to print a double with full precision on iOS?

Test case:

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

Results:

3.141593
3.141593
3.141592653589793

Conclusions:

1) Printing via NSLog() or [NSString stringWithFormat] provide a very low precision...

2) Printing via [NSNumber numberWithDouble] provides a better precision...

I would have expected to get a result much closer to the original value: 3.14159265358979323846264338327950288 (as defined in math.h)

Any clues?

like image 354
Ariel Malka Avatar asked Apr 20 '11 10:04

Ariel Malka


3 Answers

The first two lines round to 6 decimals because that's the default rounding length for printf inherited from C.

The third line displays the data with the maximum useful precision - an IEEE 754 64bit floating-point number has slightly less than 16 decimal digits of precision, so all those digits of the literal in math.h are pointless (perhaps they can be seen as future-proofing against a possible future redefinition in a format with more precision).

like image 90
Michael Borgwardt Avatar answered Oct 06 '22 14:10

Michael Borgwardt


You should use long double with a maximum formatting of 20 digits @.20Lg. The long doubles are 80-bit floating points, so you will not get a better precision than that. Be aware also that as of XCode 4.3.2 the constants are not in long double notation, even if the many digits suggest an uberlong double ;-)

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

the results are:

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)
like image 20
Jürgen Schwietering Avatar answered Oct 06 '22 13:10

Jürgen Schwietering


Try this:

NSLog(@"%.20f", M_PI);
like image 45
Claus Broch Avatar answered Oct 06 '22 12:10

Claus Broch