-1

I want to save a sequence of double into a .txt file, and read them later on in C. How can I achieve this without precision loss? What I don't know to do is how many digits I need to save? I doubt I may not get the exact double I saved if not enough digits are saved.

Below is what I have tried

doubles=[3.14159, 3.14159265358]
filename="tmp.txt"
with open(filename,'w') as f:
    for x  in doubles:
        f.write("%.16f\n" %x)

I got two (I guess) imprecise representation of my data, doubles. 3.1415899999999999 3.1415926535800001

This is undesirable. I want data to be stored as is, so that another program can retrieve them exactly. Any idea?

zell
  • 9,830
  • 10
  • 62
  • 115
  • https://stackoverflow.com/q/21895756/7076153 – Stargateur Jun 25 '18 at 12:41
  • (Python) floats have some limitations: https://docs.python.org/3/tutorial/floatingpoint.html – Mike Scotty Jun 25 '18 at 12:41
  • You can save them as binary, however, then they are not necesarilly transportable to other machines with other architectures. – Paul Ogilvie Jun 25 '18 at 12:41
  • Why not do you store them as a fractions? – Jose Jun 25 '18 at 12:43
  • @PaulOgilvie - Actually, you _can_ store floating point numbers in such a way as to preserve their precision. But you have to put bounds on to how precise you need to be. (and as I was typing this comment, Bathsheba's answer appeared). – ryyker Jun 25 '18 at 12:44
  • You can `sprintf` them using the `%a` format as long as you don't mind them not being (average) human-readable! However, this is only supported by C, not Python. – Ian Abbott Jun 25 '18 at 12:57
  • 1
    @JoseFelipe - Fractions would work for storing only rational numbers. What about irrationals? eg. what fraction would you suggest for storing `PI`? – ryyker Jun 25 '18 at 12:58
  • @ryyker good point, that was a stupid question of mine. Thank you. – Jose Jun 25 '18 at 13:02
  • To write, use exponential format, not `"f"`. The C-ish answer is `"%.*g", DBL_DECIMAL_DIG ,x` or `"%.*e", DBL_DECIMAL_DIG - 1, x` or `"%a", x` – chux - Reinstate Monica Jun 25 '18 at 14:00
  • 1
    @ryyker Re: [What about irrationals?](https://stackoverflow.com/questions/51023663/saving-and-reading-doubles-without-precision-loss#comment89040494_51023663): All finite `double` are rational, so irrationals do not apply to "Saving and Reading doubles without precision loss". Even the common `M_PI`, a close approximation of π, is rational – chux - Reinstate Monica Jun 25 '18 at 14:31
  • @JoseFelipe Storing the `double` as an exact fraction is a reasonable approach that has some merits. – chux - Reinstate Monica Jun 25 '18 at 14:41

1 Answers1

3

From C11, use DBL_DECIMAL_DIG which is defined exactly for this use: See https://en.cppreference.com/w/c/types/limits. It tells you the number of decimal digits of precision required such that a load of a saved double, followed by a save then a reload will mean that the two load steps will always return the same double.

DBL_DECIMAL_DIG is normally 17.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • `DBL_DIG` is insufficient. Use `DBL_DECIMAL_DIG`. – chux - Reinstate Monica Jun 25 '18 at 13:47
  • @chux: May as well remove the old `DBL_DIG` unless that's against C tag ettiquette: In C++ now we seem to have a consensus in accepting that C++11 is the default standard. – Bathsheba Jun 25 '18 at 13:49
  • 2
    `DBL_DIG` remains useful. It is the most digits that text-`double`-text can round-trip correctly for all `double`. These 2 macros apply in different situations. – chux - Reinstate Monica Jun 25 '18 at 13:51
  • When `DBL_DECIMAL_DIG` is not available, code can use `DBL_DIG + 3` to derive the digits needed for `double`-text-`double` as in OP's case. It might be a tad more than `DBL_DECIMAL_DIG`, but never too small. – chux - Reinstate Monica Jun 25 '18 at 13:56