0

For example lets take the value 10.23E-4. What I did was break it up into several variables, whole=10, decimal=23, decimalLength=2, isNegative=1, exponent=4 (is there a better name for these?)

First I d = decimal; d*/exp10(decimalLength); d+=whole;. This gets me 10.23. Next I wrote e = exp10(exponent); if (isNegative) e = 1/e; result = d*e;. I suspect this part is wrong. My result is 0.0010229999999999998 while strtod is 0.001023. What's the proper way to handle the exponent? Is there a good+fast implementation of strtod I can compare my code to?

Eric Stotch
  • 141
  • 4
  • 19
  • Possibly related: https://stackoverflow.com/questions/588004/is-floating-point-math-broken. If you want to see how `strtod` is implemented elsewhere, glibc is open source. – Stephen Newell May 09 '22 at 21:05
  • 1
    [Buckle up!](https://www.exploringbinary.com/how-glibc-strtod-works/) – Brett Hale May 09 '22 at 21:08
  • 3
    "My result is 0.0010229999999999998 while strtod is 0.001023" -- considering the implementation of floating point numbers this is an acceptable error. – Thomas Dignan May 09 '22 at 21:18
  • @BrettHale nice. But after reading the "Converting the Fractional Part" I still have no idea how to get the value without using a loop. One other test I saw uses `E-173` and I don't want to divide 173 times – Eric Stotch May 09 '22 at 21:29
  • The quick-and-dirty way is more or less as you've outlined, and it's possible to get decent results. I normally don't keep `whole`, `decimal`, and `decimalLength` as separate variables: I just start doing a decimal conversion, and if I see a `'.'` I set a flag indicating I've seen it, and start a separate count of what will become my exponent, so by the end of the "significand" part, I've got `whole` = 1023 and `exponent` = -2. Then after scanning the `E-4` part I adjust exponent by subtracting 4. At that point I can just compute `1023 * pow(10, -6)`. (But this fails if `whole` overflows.) – Steve Summit May 09 '22 at 21:40
  • The official name for the `10.23` part is [*significand*](https://en.wikipedia.org/wiki/Significand). (Many people call it the "mantissa", but it turns out that's kinda wrong.) – Steve Summit May 09 '22 at 21:44
  • @SteveSummit What is the `10` called? Interesting `pow(10, val)` seems to give me a good result. But now I have to look into how to rewrite this in assembly. – Eric Stotch May 09 '22 at 21:47
  • 1
    @EricStotch Which 10? The 10 in `10.23`, or the 10 in `pow(10, -6)`? The 10 in `10.26` is the "whole part". The 10 in `pow(10, -6)` is the *base* or *radix*. I could have used `exp10(-6)` like you did in the question. – Steve Summit May 09 '22 at 21:49
  • If you find yourself computing 10^N yourself (for integer N), read up on [binary exponentiation](https://en.wikipedia.org/wiki/Binary_exponentiation). – Steve Summit May 09 '22 at 21:51
  • @SteveSummit ty I'm on it. Also I thought exp10 didn't accept negative values for some reason. That fixed my code right up – Eric Stotch May 09 '22 at 21:52
  • Only problem with `exp10()` is that it's not as standard. – Steve Summit May 09 '22 at 21:53

0 Answers0