Sun
Sun

Reputation: 4718

Short.Parse with decimal fails

I have a decimal value

decimal myDecimal = 19.0000M;

I'm trying to convert this to a short value.

short newVal;
short.TryParse(myDecimal.ToString(), out newVal); // False

but this fails. If I use a double it is fine.

Why does this fail?

Thanks

Upvotes: 4

Views: 3249

Answers (6)

Gilad Green
Gilad Green

Reputation: 37281

The Problem

  • The problem is that this overload of TryParse takes that number as an NumberStyles.Integer - meaning it is looking for a format that does not contain any .. seeing in Reference Source it is actually doing this:

    public static bool TryParse(String s, out Int16 result) {
       return TryParse(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result);
    }
    
  • To show that the . is the problem change as following and it will work:

    decimal myDecimal = 19M;
    var succeeded = short.TryParse(myDecimal.ToString(), out newVal);
    

How Does Double work but decimal fails

The reason why with double it works is because of how it is returned in the ToString:

decimal val1 = 19.00M;
double val2 = 19.00;

val1.ToString() // "19.00"
val2.ToString() // "19"

The Fix

To be able to parse your original input use instead the overload where you provide the NumberStyle and Format:

var succeeded = short.TryParse(myDecimal.ToString(), NumberStyles.Number, NumberFormatInfo.CurrentInfo,  out newVal);

The NumberStyle.Number allows:

  • AllowLeadingWhite, AllowTrailingWhite, AllowLeadingSign, AllowTrailingSign, AllowDecimalPoint, AllowThousands

Upvotes: 2

user1562155
user1562155

Reputation:

It doesn't work because myDecimal.ToString() returns a decimal number string: 19.000 and short.Tryparse() accepts only integer strings.

The solution is not to convert to string but directly between decimal and short (as luki shows):

short shortVal = Convert.ToInt16(myDecimal);

Upvotes: 0

mybirthname
mybirthname

Reputation: 18137

You should AllowDecimalPoint with parsing of short in other case the parsing will fail: DonNetFiddle

decimal myDecimal = 19.0000M;
short newVal;

short.TryParse(myDecimal.ToString(), NumberStyles.AllowDecimalPoint , CultureInfo.InvariantCulture, out newVal);

Upvotes: 1

eocron
eocron

Reputation: 7546

Remember, decimal saves digits after floating point as well. So, mathematicaly equal numbers will give different effect when printed:

decimal myDecimal = 19.0000M;
decimal myDecimal2 = 19.000000M;
Console.WriteLine(myDecimal.ToString());
Console.WriteLine(myDecimal2.ToString());

//OUTPUT
19,0000
19,000000

Upvotes: 0

kashi_rock
kashi_rock

Reputation: 557

including culture and number style will be better approach:

short.TryParse(myDecimal.ToString(), NumberStyles.Integer | NumberStyles.AllowDecimalPoint, 
           System.Globalization.CultureInfo.InvariantCulture, out newVal);

Upvotes: 4

luki
luki

Reputation: 72

Try: Convert.ToInt16(myDecimal);

Upvotes: -2

Related Questions