tags:

views:

301

answers:

2

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.

A: 

Hi,
see how the regional settings are set for this computer it might be that "." is set as thousand separator not as decimal separator. Try using Decimal.TryParse (String, NumberStyles, IFormatProvider, out Decimal val) and pass NumberFormatInfo created with decimal separator "."

IordanTanev
OP has already said there are no differences in the regional settings - plus if 1.000 was input when `.` was a thousand separator, it would give 1000, not 0.
Andy Shellam
+16  A: 

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;
Kobi
Interesting answer, but it begs the question that if Regional Settings doesn't allow you to set the positive sign, and the OP's regional settings are the same as the other machines, how could the positive sign have been changed? I'm not disagreeing with you, it fits the examples perfectly, I'm just curious.
Andy Shellam
And we have a winner! Just ran the following code on his machine: Console.WriteLine(System.Globalization.CultureInfo.CurrentCulture.NumberFormat.PositiveSign); and it outputs "1". Now, just need to figure out how to change this back...
Martin Harris
I bet it was a third party program that did this. What a monstrosity.
Kugel
Happy to help. I can't find a registry setting for this (should be on `HKEY_CURRENT_USER\Control Panel\International` ), but maybe it can be added.
Kobi