Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

decimal.TryParse() drops leading "1"

Tags:

.net

Short and sweet version:

On one machine out of around a hundred test machines decimal.TryParse() is converting "1.01" to 0.01


Okay, this is going to sound crazy but bear with me...

We have a client applications that communicates with a webservice through JSON, and that service returns a decimal value as a string so we store it as a string in our model object:

[DataMember(Name = "value")]
public string Value { get; set; }

When we display that value on screen it is formatted to a specific number of decimal places. So the process we use is string -> decimal then decimal -> string.

The application is currently undergoing final testing and is running on more than 100 machines, where this all works fine. However on one machine if the decimal value has a leading '1' then it is replaced by a zero. I added simple logging to the code so it looks like this:

Log("Original string value: {0}", value);
decimal val;
if (decimal.TryParse(value, out val))
{
    Log("Parsed decimal value: {0}", val);
    string output = val.ToString(format, CultureInfo.InvariantCulture.NumberFormat);
    Log("Formatted string value: {0}", output);
    return output;
}

On my machine - any every other client machine - the logfile output is:

  • Original string value: 1.010000
  • Parsed decimal value: 1.010000
  • Formatted string value: 1.01

On the defective machine the output is:

  • Original string value: 1.010000
  • Parsed decimal value: 0.010000
  • Formatted string value: 0.01

So it would appear that the decimal.TryParse method is at fault.

Things we've tried:

  • Uninstalling and reinstalling the client application
  • Uninstalling and reinstalling .net 3.5 sp1
  • Comparing the defective machine's regional settings for numbers (using English (United Kingdom)) to those of a working machine - no differences.

Has anyone seen anything like this or has any suggestions? I'm quickly running out of ideas...


While I was typing this some more info came in: Passing a string value of "10000" to Convert.ToInt32() returns 0, so that also seems to drop the leading 1.


Further tests based on comments:

  • 1.01 -> 0.01
  • 111.01 -> 11.01
  • 123.01 -> 23.01
  • 231.01 -> 231.01
  • 01.01 -> 1.01

So it would appear that it only affects 1s and only if they are the first character of the string. Very odd, but at least it's consistent.

like image 308
Martin Harris Avatar asked Mar 30 '10 09:03

Martin Harris


1 Answers

I am able to reproduce your results. Consider:

public NumberFormatInfo OneIsPositiveSignFormat()
{
    NumberFormatInfo custom = new NumberFormatInfo();
    custom.PositiveSign = "1";
    return custom;
}

And then:

if (decimal.TryParse(value, NumberStyles.Number, OneIsPositiveSignFormat(), out val))

The thing is: Regional Settings does not show you the current positive sign, and mainly: you did not set the culture when parsing the number.

The value may come from various locations: It may have come from the registry as the system defaults, or the defaults could have been set by code:

CultureInfo customCulture = (CultureInfo)CultureInfo.InvariantCulture.Clone();
customCulture.NumberFormat = OneIsPositiveSignFormat();
Thread.CurrentThread.CurrentCulture = customCulture;
like image 188
Kobi Avatar answered Sep 18 '22 13:09

Kobi