docs(tools): stop over-quantifying what String does to a big integral double

The pyScalar paragraph read as a universal over every beyond-safe-range
integral number, and three of its clauses have counterexamples inside
that very domain: String(2 ** 53) and String(1e20) are byte-identical to
BigInt's digits, so the "different integer or no integer literal at all"
split is not exhaustive, "the 16 digits" is 2 ** 60's instance count
rather than the mechanism (shortest round-trip is 1 to 17 significant
digits), and padded digits do name a held integer for 1e20. Say shortest
decimal string then padded to the exponent, give both counts, condition
the no-double-holds-it clause, and state the invariant that makes the
rule unconditional: where String is already exact the two agree, and
where it is not, BigInt is the exact one.

Also align one README.zh.md term: the same file already translates
"exotic names" as 特殊名称 in the SDK-section bullet.
This commit is contained in:
Chinesezjc
2026-08-05 20:06:06 +08:00
parent 5d65686c33
commit 2cb0dddb40
3 files changed
+16 -12

No files matched your search

+14 -10
View File
@@ -304,16 +304,20 @@ function childClassName(base: string, segment: string): string {
*
* A beyond-safe-range integral number takes `BigInt` digits rather than
* `String`: Python integers are arbitrary-precision, so the emitted digits ARE
* the value the model programs against, and `String` gives a different integer
* than the double holds (`2 ** 60` prints the rounded `...847000`, not the
* exact `...846976`) or no integer literal at all (`1e21` prints `1e+21`).
* `String`'s rounding is not a bug in it: `Number::toString` is shortest
* round-trip, so it emits the 16 digits that re-read to the same double and
* pads with zeros, and those padded digits name an integer no double holds.
* Passing one back would have to cross the argument boundary as a JSON number
* — a double again — so the SDK would document a value no program can pass.
* The TS flavor needs no counterpart: its literal is re-read by a JS parser
* back into the same double.
* the value the model programs against, and `String` can give a different
* integer than the double holds (`2 ** 60` prints the rounded `...847000`, not
* the exact `...846976`) or no integer literal at all (`1e21` prints `1e+21`).
* `String`'s rounding is not a bug in it: `Number::toString` emits the shortest
* decimal string that re-reads to the same double, then pads to the exponent
* with zeros (1 significant digit for `1e20`, 16 for `2 ** 60`) — and when the
* shortest string is shorter than the double's exact value, those padded digits
* name an integer no double holds. Passing one back would have to cross the
* argument boundary as a JSON number — a double again — so the SDK would
* document a value no program can pass. `BigInt` needs no case split: where
* `String` is already exact (`2 ** 53`, `1e20`) the two agree byte for byte,
* and where it is not, `BigInt` is the exact one. The TS flavor needs no
* counterpart at all: its literal is re-read by a JS parser back into the same
* double.
*
* `JSON.stringify` is also what keeps this path's output parseable, and it is
* the only thing that does. It covers both classes of hazard: the two kinds of