Skip to content

Commit a0499e8

Browse files
committed
0.8.5 don’t overflow on very long fractions #52
1 parent b15f3da commit a0499e8

File tree

2 files changed

+32
-5
lines changed

2 files changed

+32
-5
lines changed

src/parser.rs

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -432,11 +432,33 @@ impl<'a> Parser<'a> {
432432
let mut p = 1u64;
433433
let mut f = 0u64;
434434

435-
// FIXME: prevent overflowing!
436-
read_num!(self, digit, {
437-
f = (f << 1) + (f << 3) + digit as u64;
438-
p = (p << 1) + (p << 3);
439-
});
435+
loop {
436+
// Avoid overflow, switch to operating on f64
437+
if p != 10000000000000000000 {
438+
num += (f as f64) / (p as f64);
439+
440+
let mut p = 0.1;
441+
442+
read_num!(self, digit, {
443+
num += (digit as f64) * p;
444+
p /= 10.0;
445+
});
446+
break;
447+
}
448+
449+
// Carry on with u64
450+
let ch = next_byte!(self || break);
451+
match ch {
452+
b'0' ... b'9' => {
453+
f = (f << 1) + (f << 3) + (ch - b'0') as u64;
454+
p = (p << 1) + (p << 3);
455+
},
456+
_ => {
457+
self.index -= 1;
458+
break;
459+
}
460+
}
461+
}
440462

441463
num += (f as f64) / (p as f64);
442464
} else {

tests/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,11 @@ mod unit {
329329
assert_eq!(parse("3.141592653589793").unwrap(), 3.141592653589793);
330330
}
331331

332+
#[test]
333+
fn parse_very_long_float() {
334+
assert_eq!(parse("2.22507385850720113605740979670913197593481954635164564e-308").unwrap(), 2.2250738585072e-308);
335+
}
336+
332337
#[test]
333338
fn parse_integer() {
334339
assert_eq!(parse("42").unwrap(), 42);

0 commit comments

Comments
 (0)