CLAUDE WATERMARK REMOVER · PRACTICAL TEST
Why does Intl.NumberFormat show 2,500% for a cleaned value of 25?
Our en-US percent formatter displays 0.25 as 25% and 25 as 2,500%. The literal text 25% converts to NaN in this test. Cleanup repairs the marked fraction but does not choose whether your field stores ratios or percentage points.
Open the Claude text cleaner · Full measured data
Measured inputs and outputs
These are locally constructed test strings, not evidence that Claude inserts these characters. We executed the saved homepage script snapshot with a minimal DOM harness and compared exact strings. The invisible-checkbox state and dash mode appear in each row. The observations below test this page's specific question. Destination observations run independently on the exact input and cleaned strings in the recorded Node runtime. We make no detector-score or statistical-watermark removal claim.
| Fixture and mode | Input string and code points | Output and cleaner status | Observed before / after |
|---|---|---|---|
| Marked fraction direct string / keep / invisible true | "0.25"U+0030 U+002E U+0032 U+200B U+0035 | "0.25"Removed 1 invisible character | {"numberLabel":"NaN","finite":false,"display":"NaN%","parts":[{"type":"nan","value":"NaN"},{"type":"percentSign","value":"%"}]}{"numberLabel":"0.25","finite":true,"display":"25%","parts":[{"type":"integer","value":"25"},{"type":"percentSign","value":"%"}]} |
| Fraction direct string / keep / invisible true | "0.25"U+0030 U+002E U+0032 U+0035 | "0.25"No selected invisible characters found | {"numberLabel":"0.25","finite":true,"display":"25%","parts":[{"type":"integer","value":"25"},{"type":"percentSign","value":"%"}]}{"numberLabel":"0.25","finite":true,"display":"25%","parts":[{"type":"integer","value":"25"},{"type":"percentSign","value":"%"}]} |
| Whole percent-looking value direct string / keep / invisible true | "25"U+0032 U+0035 | "25"No selected invisible characters found | {"numberLabel":"25","finite":true,"display":"2,500%","parts":[{"type":"integer","value":"2"},{"type":"group","value":","},{"type":"integer","value":"500"},{"type":"percentSign","value":"%"}]}{"numberLabel":"25","finite":true,"display":"2,500%","parts":[{"type":"integer","value":"2"},{"type":"group","value":","},{"type":"integer","value":"500"},{"type":"percentSign","value":"%"}]} |
| Percent suffix direct string / keep / invisible true | "25%"U+0032 U+0035 U+0025 | "25%"No selected invisible characters found | {"numberLabel":"NaN","finite":false,"display":"NaN%","parts":[{"type":"nan","value":"NaN"},{"type":"percentSign","value":"%"}]}{"numberLabel":"NaN","finite":false,"display":"NaN%","parts":[{"type":"nan","value":"NaN"},{"type":"percentSign","value":"%"}]} |
Two finite numeric inputs represent different scales
The marked input places U+200B between the two and five in 0.25. Number conversion is NaN before deletion, and the percent formatter displays NaN%. After deletion, conversion produces the finite ratio 0.25 and the display becomes 25%. The plain 0.25 control agrees with that final display without a cleanup event. The 25 control is also a finite number but formats as 2,500%, including the English grouping separator. We record numeric labels, finiteness and formatToParts output so the factor-of-one-hundred display difference is not hidden by a generic successful-format flag. The source of that difference is the supplied numeric scale rather than an extra digit inserted by the cleaner.
A written percent suffix is not parsed by this formatter path
The 25% text control is passed through Number first, which yields NaN; the observer then formats that NaN value. It does not invoke a percentage-text parser or strip the suffix. This unchanged control shows why a human-readable percentage label and the numeric input expected by a formatter are different representations. Earlier pages discuss localized decimal formatting and parsing the display back through Number. Here the locale is fixed and the question is which numeric unit enters percent formatting in the first place. We test four small authored strings, no financial instrument, performance return, statistical dashboard or measured business data. Runtime internationalization metadata is retained with the public evidence.
Define ratios and percentage points at the field boundary
Document whether the field stores a ratio such as 0.25 or a percentage-point quantity such as 25 before selecting its display path. If the latter is the intended data contract, perform any required conversion deliberately and verify it with a known reference; the cleaner cannot infer the unit from the digits. Check type and finiteness separately from a formatter returning text. Retain the original suffix-bearing value when the application accepts human-entered percentage notation and use its own defined parser. Our matrix supplies reproducible controls for scale confusion without choosing a universal input convention. A repaired numeric spelling and a plausible percent label provide no evidence about authorship or removal of a statistical watermark.
Reproduce this test
Save reproduce.cjs and tested-app.js in the same folder. Run the command below with Node.js. The harness prints its runtime, script SHA-256 and every measured row. Compare those rows with the original record. Using a newer script or runtime creates a new experiment; retain the version information with your rerun.
node reproduce.cjsReference and next check
ECMA-402 number formatting provides the relevant primary definition. The table and fixture analysis are original measurements. For broader inspection, use our Unicode inspector. Read the scope distinction before interpreting cleanup as a watermark result.