0

I read these and it didn't seem to answer my question Correct strtod implementation? How do I implement strtod?

From this post I got the min/max double What are the actual min/max values for float and double (C++)

In C I can write this line just fine

double d = -179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.0

Trying to parse a string of it (and the positive max value) is a different story. The code works up until the last digit (the 8) where I get inf on the *10 line. Essentially I wrote

double result=0; for loop { result = result*10; result = result+singleDigit }

strtod handles it just fine and I can't understand any implementation I see online. It becomes inf on the multiplication line. How the heck do I get the last digit?

Ned
  • 33
  • 4
  • Do you have this problem only for negative numbers? – Barmar Nov 14 '22 at 17:44
  • I haven't looked at any `strtod` implementations, but they probably use something like Kahan summation to reduce the numerical errors at each step (because the intermediate values cannot be represented exactly as a binary floating point number). – Ian Abbott Nov 14 '22 at 17:47
  • @IanAbbott I'm reading the wikipedia. It appears its to accurately sum numbers? I couldn't figure out how to get the last exponent from it – Ned Nov 14 '22 at 17:57
  • @Barmar no. Both the positive and negative max causes it. One digit less on both is fine – Ned Nov 14 '22 at 17:58
  • You could look at the source code of `strtod()` since there are open source C libraries. – Barmar Nov 14 '22 at 18:01
  • It probably works directly with the bits of the floating point numbers, so it doesn't have problems at the limits of precision. – Barmar Nov 14 '22 at 18:02
  • You're probably running into problems due to round-off error when multiplying. – Barmar Nov 14 '22 at 18:02
  • @Barmar you appear to be correct. One digit less of max I'm seeing different numbers. The two digits before e+ is wrong. `1.7976931348623145e+307` when I expect `1.7976931348623158e+307`. – Ned Nov 14 '22 at 18:08
  • You didn't show the actual code but when I tried the algorithm you seem to show, the value diverges at the 16th digit, which is what you showed in the last comment. OTOH `strtod` is exact. – Weather Vane Nov 14 '22 at 18:09
  • Rounding errors start when the 17th digit is processed. The digits up to that point are “17976931348623157”, but the parsed value is 17976931348623156. Rounding errors continue each time `result = result*10` is evaluated, sometimes upward, sometimes downward. It so happens the final result ends up rounded too high, yielding infinity. You need a different algorithm for converting from decimal to binary floating-point. I know there has been recent work on algorithms for converting from binary floating-point to decimal, but I am not familiar with recent work for the reverse. – Eric Postpischil Nov 14 '22 at 18:16
  • The simple approach is to use grade-school arithmetic. Create an array containing all digits. Record the low bit of the last digit. Then divide the array by 2, using long division from elementary school. Repeat. That will give you a string of bits, produced in reverse order. That should give you a string with 53 1 bits followed by 0 bits. For the general case, you would take the first 53 bits, round down if the next bit is 0 or round up if the next bit is 1 and there is any other 1 bit in the tail. If it is a 1 followed by all zeros, round to make the 53rd bit even… – Eric Postpischil Nov 14 '22 at 18:19
  • … then set the exponent according to how many bits there are. – Eric Postpischil Nov 14 '22 at 18:19
  • Real-life implementations need to be very complicated to avoid these problems. – Ian Abbott Nov 14 '22 at 18:20
  • Sample C++ code is in [this answer](https://stackoverflow.com/a/58309048/298225). It is not a full `strotod` implementation; it does not handle exponents. – Eric Postpischil Nov 14 '22 at 18:26
  • @EricPostpischil thanks. I read up until the code. I'll try to follow the code tonight or on the weekend – Ned Nov 14 '22 at 22:00

0 Answers0