strconv.parse_f64_prefix() returns incorrect values for negative numbers
Closed this issue · 2 comments
divanburger commented
Context
- Operating System & Odin Version:
Odin: dev-2024-10:9f609dd74
OS: openSUSE Tumbleweed, Linux 6.11.0-1-default
CPU: AMD Ryzen 9 5900X 12-Core Processor
RAM: 31989 MiB
Backend: LLVM 18.1.8
Expected Behavior
When running the following Odin program, using odin run .
:
package strconv_test
import "core:strconv"
import "core:fmt"
test :: proc(str: string) {
val, num, ok := strconv.parse_f64_prefix(str)
fmt.println(str)
fmt.println("->", val, num, ok)
}
main :: proc() {
test("80")
test("160")
test("-80")
test("-160")
}
I expect the output to be:
80
-> 80 2 true
160
-> 160 3 true
-80
-> -80 3 true
-160
-> -160 4 true
Current Behavior
Instead I get:
80
-> 80 2 true
160
-> 160 3 true
-80
-> -79.86500349943526 3 true
-160
-> -159.73000699887052 4 true
I understand floating point numbers are not 100% accurate but for negative numbers that seems to be very wrong
tf2spi commented
That would indeed be very wrong. Especially for f64
, integers with abs(x) < (1 << 54)
are supposed to be representable without truncating.
tf2spi commented
In core/strconv/strconv.odin
f := f64(mantissa)
if neg {
f = -f
}
switch {
case exp == 0:
return f, nr, true
case exp > 0 && exp <= 15+22:
if exp > 22 {
f *= pow10[exp-22]
exp = 22
}
if f > 1e15 || f < 1e-15 {
break trunc_block
}
return f * pow10[exp], nr, true
case -22 <= exp && exp < 0:
return f / pow10[-exp], nr, true
}
If neg
is true, then f < 0
, so f < 1e-15
, so it's always breaking on trunc_block
when it was intended to return f * pow10[exp]
.