views:

119

answers:

3

I tried to assign a very small number to a double value, like so:

double verySmall = 0.000000001;

9 fractional digits. For some reason, when I multiplicate this value by 10, I get something like 0.000000007. I slighly remember there were problems writing big numbers like this in plain text into source code. Do I have to wrap it in some function or a directive in order to feed it correctly to the compiler? Or is it fine to type in such small numbers in text?

+5  A: 

The problem is with floating point arithmetic not with writing literals in source code. It is not designed to be exact. The best way around is to not use the built in double - use integers only (if possible) with power of 10 coefficients, sum everything up and display the final useful figure after rounding.

Crimson
And storage, no?
strager
Yes, the representation itself is inexact.
Crimson
built in double? what do you mean with that? I have used the plain naked double. Is there another one?
HelloMoon
No, not another primitive double but a specially constructed class from a library - See T.J. Crowder's response for examples.
Crimson
This is why NSDecimalNumber takes in and outputs strings, so that you don't ever need to touch the floating point types. Core Data stores NSDecimalNumbers natively, but I've used strings to store exact results in SQLite.
Brad Larson
Brad, this string IO to NSDecimalNumber is interesting. My application generates intputs for further mathematical operations which are supposed to be integers, but represented in double. Could I in this case just pass them on as mantissa with exponent 0 and get a clean integer representation in NSDecimalNumber, or should I convert it to a string and cut off all characters after the period? Would the first option be sufficient in your opinion?
HelloMoon
+1  A: 

As usual, you need to read stuff like this in order to learn more about how floating-point numbers work on computers. You cannot expect to be able to store any random fraction with perfect results, just as you can't expect to store any random integer. There are bits at the bottom, and their numbers are limited.

unwind
thanks unwind. Indeed I let Alex read all this stuff for me out loud while staring at all the formulas ;) but I think I've understood some problems even with my limited mathematical knowledge. So thanks for that great link.
HelloMoon
+3  A: 

Standard floating point numbers are not stored in a perfect format, they're stored in a format that's fairly compact and fairly easy to perform math on. They are imprecise at surprisingly small precision levels. But fast. More here.

If you're dealing with very small numbers, you'll want to see if Objective-C or Cocoa provides something analagous to the java.math.BigDecimal class in Java. This is precisely for dealing with numbers where precision is more important than speed. If there isn't one, you may need to port it (the source to BigDecimal is available and fairly straightforward).

EDIT: iKenndac points out the NSDecimalNumber class, which is the analogue for java.math.BigDecimal. No port required.

T.J. Crowder
Cocoa has the NSDecimalNumber class for this purpose. From the docs: `An instance can represent any number that can be expressed as mantissa x 10^exponent where mantissa is a decimal integer up to 38 digits long, and exponent is an integer from –128 through 127.`
iKenndac
@iKenndac: Perfect!
T.J. Crowder