Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upFloat parsing can fail on valid float literals #31407
Comments
This comment has been minimized.
This comment has been minimized.
|
cc me |
This comment has been minimized.
This comment has been minimized.
|
can't we just have a slowpath that uses 3072-bit bignums or something? I mean, for numbers with a very long number of digits, we could:
Certainly, at the worst-case, we do need to compare our string with an halfway-float, After all, |
This comment has been minimized.
This comment has been minimized.
|
@arielb1 How would you actually implement the second step? Keep in mind that this is in libcore, so we can't use float formatting because that would allocate. (Maybe you could use the underlying functions that are also in libcore, but this probably complicates everything significantly. However I have to admit that I don't even know what the interface of those functions looks like, so maybe it's not that bad.) |
This comment has been minimized.
This comment has been minimized.
|
I actually read the paper, and its Algorithm R is a variant of what I've came up with. I guess we just need to enlarge our bignums to sufficiently-many bits and use sticky bits+rounding (we don't really need 1075 digits = 3571 bits because we can skip the powers-of-2). |
steveklabnik
added
the
A-libs
label
Jul 25, 2016
nikomatsakis
referenced this issue
Sep 14, 2016
Merged
Fix ICE test in compiletest fail-tests #36335
This comment has been minimized.
This comment has been minimized.
ahrvoje
commented
Jan 22, 2017
•
|
I've gathered a collection of String to Double cases that proved to be problematic in various projects during the past few decades: Rust 1.14.0 (e8a0123 2016-12-16) for Windows fails on 17 of 81 conversion tests (C21, C22, C23, C25, C29, C37, C38, C39, C40, C64, C65, C66, C67, C68, C69, C76, C79), with the following being the shortest one (C29):
|
This comment has been minimized.
This comment has been minimized.
|
@ahrvoje That's a very nice collection of test cases, thanks for sharing! |
This comment has been minimized.
This comment has been minimized.
|
This is a regression from 1.7.0 to 1.8.0. It broke my crate (lol). |
aturon
added
regression-from-stable-to-beta
regression-from-stable-to-stable
and removed
regression-from-stable-to-beta
labels
Feb 14, 2017
This comment has been minimized.
This comment has been minimized.
eddyb
added
I-nominated
T-libs
labels
Feb 26, 2017
This comment has been minimized.
This comment has been minimized.
|
I've nominated this for discussion in the T-libs. This is T-libs area, because error comes from the floating number parsing routines in libstd/core. This is an annoying regression to me and not a nice regression to have in the compiler overall, as one cannot feed any sort of non-normal floating point numbers to the compiler (compile-time) or the parser (run-time). You can’t do something like |
This comment has been minimized.
This comment has been minimized.
|
@nagisa AFAIK for every floating point value [*] there's a canonical literal that is parsed correctly, it's just that some literals that would also result in the value don't work. Do you have a counter example? [*] Other than the bazillion NaNs with different payloads, of course, but we don't have literals for them anyway. |
This comment has been minimized.
This comment has been minimized.
|
@rkruppe my counter example is that I have no idea what the canonical literals for my denormals are and am in general paranoid enough about floats to always write them down with some extra precision. That being said, I’m gonna believe you and retract my statement that there’s no way at all to write the denormals down. |
This comment has been minimized.
This comment has been minimized.
|
If you know the bit pattern you want, you can construct the right float value via transmute and format it (either To be clear, I don't want to deflect attention away from this issue — far from it, I'd really love to see it addressed somehow, and would do so right now I had the time and energy. I'm just trying to understand how it's causing you trouble and offer workarounds in the mean time. |
This comment has been minimized.
This comment has been minimized.
|
discussed during libs triage today conclusion was we'd definitely like to fix but otherwise doesn't seem P-high, so P-medium |
alexcrichton
added
P-medium
and removed
I-nominated
labels
Feb 28, 2017
lifthrasiir
referenced this issue
Mar 21, 2017
Closed
Add support for hexadecimal float literals #1433
steveklabnik
removed
the
A-libs
label
Mar 24, 2017
rkruppe
referenced this issue
Apr 15, 2017
Closed
Float parsing sometimes fails when given too many repeating digits #41317
Mark-Simulacrum
added
the
C-bug
label
Jul 24, 2017
This comment has been minimized.
This comment has been minimized.
evanw
commented
Apr 4, 2018
|
What about falling back to a C library in the meantime? For example, using https://crates.io/crates/strtod instead of Rust's built-in parser seems to fix this bug for me. |
This comment has been minimized.
This comment has been minimized.
|
The problem is that float parsing is in |
This comment has been minimized.
This comment has been minimized.
|
Note that you can now (on nightly and beta) cast bit representations to floats inside constants: pub static F: f32 = unsafe {
union Helper {
bits: u32,
f: f32,
}
Helper { bits: 0x0000_0000 }.f
}; |
This comment has been minimized.
This comment has been minimized.
top1st
commented
Nov 20, 2018
frewsxcv
added a commit
to frewsxcv/rust
that referenced
this issue
Nov 25, 2018
frewsxcv
referenced this issue
Nov 25, 2018
Merged
Add grammar in docs for {f32,f64}::from_str, mention known bug. #56217
frewsxcv
added a commit
to frewsxcv/rust
that referenced
this issue
Nov 25, 2018
This comment has been minimized.
This comment has been minimized.
donbright
commented
Dec 1, 2018
•
|
It seems inconsistent to me that rust discourages thoughtless conversion from 64 bit to 32 bit integers, or thoughtless conversion between signed and unsigned integers, but it allows thoughtless conversion from decimal to binary. Decimal and Binary are not the same set of numbers, just like i32 and u64 are not the same set, just like binary floats and binary integers are not the same set. To be precise, (or, safe, even), maybe there could be a basic decimal number type in the language and decisions could be made about its conversion to other types. |

rkruppe commentedFeb 4, 2016
That is, it returns
Err(..)on inputs with lots of digits and extreme exponents — it doesn't (shouldn't) panic.This is a limitation of the current code that has been known since that code was originally written, but is quite nontrivial to fix, so I didn't get around to it yet. Basically one would have to implement an algorithm similar to glib's strtod and replace the current slow paths (Algorithm M and possibly Algorithm R) with it. If someone wants to have a crack at it, go ahead, just give me a heads up so we don't duplicate work. See also #27307 for some discussion.
This bug doesn't affect reasonably short (17-ish decimal digits) representations of finite (even subnormal) floats, and neither does it affect most inputs that are rounded down to zero or rounded up to infinity. The only problem are very small exponents with so many integer digits that the number can't just be rounded down to zero and can't be represented with our custom 1280-bit bignums. One example, for
f64, is1234567890123456789012345678901234567890e-340(which is a finite and normal float, about1.23456789e-301). This would be annoying on its own, but it also trips up constant evaluation in the compiler (see #31109).