Skip to content

Commit ac81dd9

Browse files
jgarzikclaude
andcommitted
rt: keep 767 digits of a long number, so UCRT sees the sticky digit
scan_number kept 800 significant digits and stood for any nonzero digit past them with one sticky 1, as the 801st. UCRT's strtod reads only 768 significant digits, so on Windows it never saw the sticky digit: a number a hair above a halfway point between two DOUBLEs (2^53+1 followed by a nonzero digit 1000 places on) rounded to even, down, and the rt test scan_reads_a_number_of_any_length failed there. 767 digits are still exact -- no DOUBLE, nor any halfway point, has more than 767 significant digits -- and the sticky digit is now the 768th. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent a3b9b10 commit ac81dd9

1 file changed

Lines changed: 7 additions & 5 deletions

File tree

‎rt/src/num.rs‎

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -135,11 +135,13 @@ const EXPONENT_MAX: i64 = 1 << 40;
135135
/// A number's significant digits, given to strtod as an integer and an
136136
/// exponent, so that a number of any length keeps its magnitude.
137137
///
138-
/// 800 digits are enough for strtod to round exactly as it would with all of
138+
/// 767 digits are enough for strtod to round exactly as it would with all of
139139
/// them: no DOUBLE, nor any point halfway between two, has more than 767
140-
/// significant digits, and the digits past the 800th, when any is not 0, are
140+
/// significant digits, and the digits past the 767th, when any is not 0, are
141141
/// stood for by one sticky 1. So the value is what strtod gives the whole
142-
/// number.
142+
/// number. No more than that: UCRT's strtod reads only 768 significant
143+
/// digits, so a sticky digit any later is ignored there, and a number just
144+
/// past a halfway point rounded to even.
143145
struct Decimal {
144146
/// Sign, digits, sticky digit, 'e', exponent, NUL.
145147
buf: [u8; Decimal::CAP],
@@ -150,7 +152,7 @@ struct Decimal {
150152
}
151153

152154
impl Decimal {
153-
const DIGITS: usize = 800;
155+
const DIGITS: usize = 767;
154156
const CAP: usize = Decimal::DIGITS + 32;
155157

156158
const EMPTY: Decimal = Decimal {
@@ -192,7 +194,7 @@ impl Decimal {
192194
if self.len == 0 {
193195
self.put(&mut at, b'0'); // "-0" is -0, as strtod read it before
194196
} else {
195-
// Past 100000 either way, 800 digits are infinity or 0 alike.
197+
// Past 100000 either way, 767 digits are infinity or 0 alike.
196198
let exponent = exponent.clamp(-100_000, 100_000) - i64::from(self.sticky);
197199
if self.sticky {
198200
self.put(&mut at, b'1');

0 commit comments

Comments
 (0)