float64 is the equivalent to double in nim
if you truly want to avoid float errors, perhaps consider using a decimal library, there should be a few of those on github
Nim's float64 is equivalent to double (And I believe float is always a float64 too).
What kind of bugs are you afraid of? While standard floating point types are not exact, it is usually only an issue in programming domains that require exact results, like finance.
is correct, float and float64 are identical in Nim
That is the case in the current Araq Nim implementation.
But it is not really defined in the Nim language specification for all Nim implementations.
so often with float, a valid string won't be parsed.
Can you give some examples? I have still no idea about your exact problem, and I never had problems with float in all the languages I have ever used.
I can construct a rounding error with 32 bit floats:
import strformat,strutils
proc atof(s:cstring):float32{.header:"stdlib.h",import.}
let num= "1.19999998"
echo &"{atof(num):.7f} != {parseFloat(num):.7f}"
produces
1.1999999 != 1.2000000
I wish I still had the example to hand. But well, it was basically parseFloat(0.00004145341") throwing an exception.
To be fair, this is one failed instance out of many thousands of passes. I'd just prefer to avoid any exceptions at all.
If you want no exceptions raised you can use parseutils.parseFloat instead of strutils.parseFloat.
If you are parsing CSV data you probably do want to handle bad inputs somehow. E.g., you can convert the "parsed too few bytes" condition into a NaN/zero/.. based on parseutils.parseFloat output if that is a safe thing to do in your broader calculations.
Philisophically, a CSV file is written in decimal (base 10) but float64 is binary (base 2), so conversion problems are not uncommon. But for most tasks, it doesn't make a real difference. A true decimal number type is slower and is typically reserved for finance and science.
I go into this with a video at the last nim conference:
https://www.youtube.com/watch?v=pfIXlXeneDE&list=PLxLdEZg8DRwTIEzUpfaIcBqhsj09mLWHx&index=12.
BTW, this conversion problem is true for all languages when going to base 2, not just Nim. It has to do with the nature of mathematic primes.
However, parsing to binary shouldn't raise an exception fault unless the number is too big to fit in 64 bits, etc.
However, parsing to binary shouldn't raise an exception fault unless the number is too big
... or is not a valid float format.
Yes, and that is the reason why I wonder why people say they have trouble.
Do you have an idea what the problem with
echo &"{atof(num):.7f} != {parseFloat(num):.7f}"
from post above should be. Why have atof() and parseFloat() to match at all -- and Nim's parseFloat() seems to be more correct.
This is explained by the 32-bit vs 64-bit effect. If you change the rounding to 8 digits, you get:
1.19999993 != 1.19999998
C's atof returns a double, but by casting it to 32-bit, you are getting a single so it fails to store the final 8 in 32 bits.
And of course, when rounding to 7 digits, a 3 rounds down and an 8 rounds up.
If you change the casting to 64 bits:
import strformat,strutils
proc atof(s:cstring):float64{.header:"stdlib.h",importc.}
let num= "1.19999998"
echo &"{atof(num):.7f} == {parseFloat(num):.7f}"
They both properly match:
1.2000000 == 1.2000000
I stand corrected. You are right, a "too large" number returns inf.
import strutils
echo $parseFloat("1.8e+308")
So, it might only be invalid strings like "xyz" that generate ValueError s.
I did not know that C's float supported infinity. Looking at IEEE 754 it also supports -inf and nan. Learned something new. I wonder why scanning "xyz" doesn't return nan. Perhaps that is reserved for divide-by-zero and other arithmetics errors.