Skip to content

Commit 76aa0d6

Browse files
fix(js/ts): fix G/g format specifier corrupting exponential notation when trimming trailing zeros
The trimEnd() call applied to the full toPrecision() result was incorrectly removing trailing zeros from the exponent part of numbers in exponential notation. For example, (1e-10).ToString("G17") would produce "1.0000000000000000e-1" instead of "1E-10" because trimEnd matched the "0" in "-10". Fix: split on the "e" separator, trim only the mantissa, then recombine with the exponent. Uppercase "G" now also correctly produces uppercase "E" in the exponent per .NET semantics. Closes #2654 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 1b67f03 commit 76aa0d6

2 files changed

Lines changed: 17 additions & 2 deletions

File tree

src/fable-library-ts/String.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -392,8 +392,15 @@ export function format(str: string | object, ...args: any[]) {
392392
break;
393393
case "g": case "G":
394394
rep = precision != null ? toPrecision(rep, precision) : toPrecision(rep);
395-
// TODO: Check why some numbers are formatted with decimal part
396-
rep = trimEnd(trimEnd(rep, "0"), ".");
395+
// Handle exponential notation: only trim trailing zeros from mantissa, not from exponent
396+
const eIdx = rep.indexOf("e");
397+
if (eIdx >= 0) {
398+
const mantissa = trimEnd(trimEnd(rep.slice(0, eIdx), "0"), ".");
399+
const exponent = rep.slice(eIdx);
400+
rep = mantissa + (format === "G" ? exponent.toUpperCase() : exponent);
401+
} else {
402+
rep = trimEnd(trimEnd(rep, "0"), ".");
403+
}
397404
break;
398405
case "n": case "N":
399406
precision = precision != null ? precision : 2;

tests/Js/Main/StringTests.fs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,14 @@ let tests = testList "Strings" [
511511
String.Format(CultureInfo.InvariantCulture, "{0:P2}", 0.1234) |> equal "12.34 %"
512512
String.Format(CultureInfo.InvariantCulture, "{0:C2}", 1000) |> equal "¤1,000.00"
513513
514+
testCase "G format specifier trims trailing zeros without corrupting exponential notation" <| fun () -> // Fix #2654
515+
(123.45).ToString("G17", CultureInfo.InvariantCulture) |> equal "123.45"
516+
(10000.0).ToString("G17", CultureInfo.InvariantCulture) |> equal "10000"
517+
(0.000222).ToString("G17", CultureInfo.InvariantCulture) |> equal "0.000222"
518+
(1e-10).ToString("G17", CultureInfo.InvariantCulture) |> equal "1E-10"
519+
(1e-10).ToString("g17", CultureInfo.InvariantCulture) |> equal "1e-10"
520+
(1.5e10).ToString("G17", CultureInfo.InvariantCulture) |> equal "15000000000"
521+
514522
testCase "ToString formatted works with decimals" <| fun () -> // See #2276
515523
let decimal = 78.6M
516524
decimal.ToString("0.000").Replace(",", ".") |> equal "78.600"

0 commit comments

Comments
 (0)