Skip to content
This repository was archived by the owner on Dec 1, 2023. It is now read-only.

Commit f54a823

Browse files
committed
decrease rounding error when parsing f64 from JSON
As the precision of a floating point number depends on its magnitude, adding each fractional digit to a large number accumulates the floating point error quite quickly. The error is accumulated much slower when assembling the fractional part separately and then finally adding it to the large number. Vide: the added test cases.
1 parent 563fc46 commit f54a823

File tree

1 file changed

+8
-1
lines changed

1 file changed

+8
-1
lines changed

src/json.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1581,17 +1581,20 @@ impl<T: Iterator<Item = char>> Parser<T> {
15811581
}
15821582

15831583
let mut dec = 1.0;
1584+
let mut frac = 0.0;
15841585
while !self.eof() {
15851586
match self.ch_or_null() {
15861587
c @ '0' ... '9' => {
15871588
dec /= 10.0;
1588-
res += (((c as isize) - ('0' as isize)) as f64) * dec;
1589+
frac += (((c as isize) - ('0' as isize)) as f64) * dec;
15891590
self.bump();
15901591
}
15911592
_ => break,
15921593
}
15931594
}
15941595

1596+
res += frac;
1597+
15951598
Ok(res)
15961599
}
15971600

@@ -2945,6 +2948,7 @@ mod tests {
29452948
assert_eq!(Json::from_str("0.4e5"), Ok(F64(0.4e5)));
29462949
assert_eq!(Json::from_str("0.4e+15"), Ok(F64(0.4e15)));
29472950
assert_eq!(Json::from_str("0.4e-01"), Ok(F64(0.4e-01)));
2951+
assert_eq!(Json::from_str("123456789.5024"), Ok(F64(123456789.5024)));
29482952
assert_eq!(Json::from_str(" 3 "), Ok(U64(3)));
29492953

29502954
assert_eq!(Json::from_str("-9223372036854775808"), Ok(I64(i64::MIN)));
@@ -2975,6 +2979,9 @@ mod tests {
29752979
let v: f64 = super::decode("0.4e-01").unwrap();
29762980
assert_eq!(v, 0.4e-01);
29772981

2982+
let v: f64 = super::decode("123456789.5024").unwrap();
2983+
assert_eq!(v, 123456789.5024);
2984+
29782985
let v: u64 = super::decode("0").unwrap();
29792986
assert_eq!(v, 0);
29802987

0 commit comments

Comments
 (0)