TLD-Save-Editor icon indicating copy to clipboard operation
TLD-Save-Editor copied to clipboard

Incorrect Scientific Notation Conversion When Parsing Floating-Point Numbers

Open jiemoL opened this issue 6 months ago • 5 comments

When reading floating-point numbers from save, values are being incorrectly converted to scientific notation with dramatically wrong exponents. This appears to be a parsing/formatting issue where decimal numbers are being misinterpreted. ​ Expected Behavior:​​

  • Input 2.00 should be parsed as 2.00
  • Input 4.00 should be parsed as 4.00
  • Input 31.10 should be parsed as 31.10

Actual Behavior:

  • 2.00 becomes 2E+09
  • 4.00 becomes 4E+09
  • 31.10 becomes 3.11097E+10

​Possible Causes:​​ In some regions, a comma (,) is used as the decimal point, while a dot (.) serves as the thousand separator. The program might misinterpret "2.00" as the thousand format for 200, and then incorrectly convert it to 2E+09. The program incorrectly treats the decimal point (.) as a thousands separator, causing '31.10' to be parsed as 3110. This value may then be erroneously amplified to 3.11097E+10 through subsequent calculations or conversions.

jiemoL avatar Jun 03 '25 14:06 jiemoL

Thanks for the detailed report. Related: #85

Note that I don't actively maintain this anymore. If someone wants this fixed, I'm accepting PRs 😄

FINDarkside avatar Jun 03 '25 18:06 FINDarkside

I've performed a thorough code review and debugging session on the relevant parsing logic, but couldn't identify any obvious issues in the immediate code path. The floating-point conversion appears to be handled correctly in isolation.

This suggests the bug might be originating from either:

  • The game engine's core number parsing routines
  • Third-party libraries/interop layers handling locale-specific formatting
  • Somewhere deeper in the data pipeline before values reach this module

Without active maintenance access to the full dependency tree, it's challenging to trace further. Would anyone from the community who's worked with the engine's low-level number formatting be able to investigate?

jiemoL avatar Jun 12 '25 04:06 jiemoL

My guess is that it has to do with the system locale. It's highly unlikely Newtonsoft.Json is the cause, so then it might be something in DynamicSerializable.cs that causes the issue.

FINDarkside avatar Jun 12 '25 06:06 FINDarkside

Hi, I added a debug line to investigate this issue. Here's what I did:

Debug.WriteLine($"Parsing number. Path: {token.Path}, JToken Type: {token.Type}, JToken Value: {token.Value<object>()}, Target Type: {t.FullName}");

I placed this line right after the following condition in DynamicSerializable.cs (around line 47):

else if (token.Type == JTokenType.Integer || token.Type == JTokenType.Float)

When parsing the save data for GEAR_BottleHydrogenPeroxide (supposed to be 0.5f), it outputs the following:

Parsing number. Path: m_LiquidLitersProxy, JToken Type: Integer, JToken Value: 500000000, Target Type: System.Single

Does this suggest that the bug is introduced during the step where the game save file is being converted to json?

325bit avatar Jul 27 '25 09:07 325bit

I believe the issue occurred when the program was reading the save file. It seems a certain version of the game implemented special handling for this value.

There was a previous update that encrypted the item list, which caused one of my mods to stop working. I think this might be a similar case, but the game still appears to correctly read standardized value formats (probably for backward compatibility with older save files).

To solve this problem, I need to understand what exactly the game is doing. For this purpose, I'm currently reverse engineering the game. However, I'm not skilled in this area, so progress is slow.

jiemoL avatar Jul 27 '25 09:07 jiemoL