Skip to content

fix(js/ts): fix G/g format specifier corrupting exponential notation when trimming trailing zeros#4587

Draft
fable-repo-assist[bot] wants to merge 2 commits intomainfrom
repo-assist/fix-g-format-exponential-2654-80866640e511f169
Draft

fix(js/ts): fix G/g format specifier corrupting exponential notation when trimming trailing zeros#4587
fable-repo-assist[bot] wants to merge 2 commits intomainfrom
repo-assist/fix-g-format-exponential-2654-80866640e511f169

Conversation

@fable-repo-assist
Copy link
Copy Markdown
Contributor

🤖 This PR was created by Repo Assist, an automated AI assistant.

Summary

Fixes a bug in the G/g format specifier for floating-point numbers where trailing zero trimming was incorrectly applied to numbers in exponential notation, corrupting the exponent.

Closes #2654

Root Cause

In String.ts, the G/g format handler calls toPrecision(rep, precision) which can return results in exponential notation (e.g., "1.0000000000000000e-10"). The subsequent trimEnd(rep, "0") was applied to the full string, incorrectly trimming trailing zeros from the exponent part. For example:

  • (1e-10).toPrecision(17)"1.0000000000000000e-10"
  • After trimEnd(rep, "0")"1.0000000000000000e-1" ❌ (wrong: trimmed "0" from "-10")

Fix

Split on the "e" separator before trimming: trim trailing zeros only from the mantissa, then recombine with the exponent. Additionally, uppercase "G" now correctly produces uppercase "E" in the exponent per .NET semantics.

const eIdx = rep.indexOf("e");
if (eIdx >= 0) {
  const mantissa = trimEnd(trimEnd(rep.slice(0, eIdx), "0"), ".");
  const exponent = rep.slice(eIdx);
  rep = mantissa + (format === "G" ? exponent.toUpperCase() : exponent);
} else {
  rep = trimEnd(trimEnd(rep, "0"), ".");
}

Changes

Tests Added

(123.45).ToString("G17", CultureInfo.InvariantCulture) |> equal "123.45"
(10000.0).ToString("G17", CultureInfo.InvariantCulture) |> equal "10000"
(0.000222).ToString("G17", CultureInfo.InvariantCulture) |> equal "0.000222"
(1e-10).ToString("G17", CultureInfo.InvariantCulture) |> equal "1E-10"
(1e-10).ToString("g17", CultureInfo.InvariantCulture) |> equal "1e-10"
(1.5e10).ToString("G17", CultureInfo.InvariantCulture) |> equal "15000000000"

CI will validate the build and tests.

Generated by 🌈 Repo Assist, see workflow run. Learn more.

To install this agentic workflow, run

gh aw add githubnext/agentics/workflows/repo-assist.md@51c8f6ad4357d2ecc06e47120031b3d75e80227d

…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>
@fable-repo-assist fable-repo-assist Bot added automation Automated changes bug javascript repo-assist Created by Repo Assist TypeScript labels May 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

automation Automated changes bug javascript repo-assist Created by Repo Assist TypeScript

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Double-to-string format using "G17" does not match .NET

0 participants