jamesmontemagno / Xamarin.Plugins

Cross-platform Native API Access from Shared Code!
MIT License
1.3k stars 380 forks source link

Settings: Storing and retrieving double.MaxValue throws OverflowException (doubles can also lose precision) #286

Closed dvshub closed 8 years ago

dvshub commented 8 years ago

Please take a moment to fill out the following (change to preview to check or place x in []):

This is a

Which plugin does this impact:

Version Number of Plugin: 2.1.0 Device Tested On: Nexus 6P, Android version 6.0.1 Simulator Tested On: iPhone 6s, iOS version 9.2

Expected Behavior

If I store the value double.MaxValue and later retrieve it, I should get the same value back.

Actual Behavior

  1. double.MaxValue is stored without issues, but while retrieving the value, it throws OverflowException.
  2. If I store 0.12345678901234567, when I retrieve it, I get 0.123456789012346, so I lose precision and what I get is not what I set.

    Steps to reproduce the Behavior

Settings.AddOrUpdateValue("key", double.MaxValue); double d = Settings.GetValueOrDefault("key", 0.0D); // throws OverflowException

This is an issue not just with double.MaxValue but with any number that needs more than 15 digits for representation. This is actually because of the way doubles are converted to strings in .Net (since that is what the Settings library does when storing double values). When converting the number to string, the value will be rounded off to 15 digits if it needs more than 15 digits for representation. E.g., if the original number is 0.12345678901234567, converting it to string results in "0.123456789012346", and converting it back to double results in 0.123456789012346, which is not what you started with.

Consider the following C# .Net code. double originalDouble = double.MaxValue; string doubleAsString = Convert.ToString(originalDouble, System.Globalization.CultureInfo.InvariantCulture); double roundtripDouble = Convert.ToDouble(doubleAsString, System.Globalization.CultureInfo.InvariantCulture); // this last conversion throws Overflow exception

This issue can be overcome by using format specifiers “R” and “G17”. More info at https://msdn.microsoft.com/en-us/library/kfsatb94(v=vs.110).aspx “In some cases, Double values formatted with the "R" standard numeric format string do not successfully round-trip if compiled using the /platform:x64 or /platform:anycpu switches and run on 64-bit systems. To work around this problem, you can format Double values by using the "G17" standard numeric format string. " https://msdn.microsoft.com/en-us/library/dwhawy9k(v=vs.110).aspx#RFormatString

Also discussed at http://stackoverflow.com/questions/766918/convert-1-79769313486232e308-to-double-without-overflowexception

jamesmontemagno commented 8 years ago

This issue was moved to jamesmontemagno/SettingsPlugin#4