Decimal ToString() conversion issue in C#
Solution 1
Decimal
preserves any trailing zeroes in a Decimal
number. If you want two decimal places instead:
decimal? decimalValue = .1211m;
string value = ((decimal)(decimalValue * 100)).ToString("#.##")
http://msdn.microsoft.com/en-us/library/0c899ak8.aspx
or
string value = ((decimal)(decimalValue * 100)).ToString("N2")
http://msdn.microsoft.com/en-us/library/dwhawy9k.aspx
From System.Decimal
:
A decimal number is a floating-point value that consists of a sign, a numeric value where each digit in the value ranges from 0 to 9, and a scaling factor that indicates the position of a floating decimal point that separates the integral and fractional parts of the numeric value.
The binary representation of a Decimal value consists of a 1-bit sign, a 96-bit integer number, and a scaling factor used to divide the 96-bit integer and specify what portion of it is a decimal fraction. The scaling factor is implicitly the number 10, raised to an exponent ranging from 0 to 28. Therefore, the binary representation of a Decimal value is of the form, ((-296 to 296) / 10(0 to 28)), where -296-1 is equal to MinValue, and 296-1 is equal to MaxValue.
The scaling factor also preserves any trailing zeroes in a Decimal number. Trailing zeroes do not affect the value of a Decimal number in arithmetic or comparison operations. However, >>trailing zeroes can be revealed by the ToString method if an appropriate format string is applied<<.
Remarks:
- the decimal multiplication needs to be casted to decimal, because
Nullable<decimal>.ToString
has no format provider -
as Chris pointed out you need to handle the case that the
Nullable<decimal>
isnull
. One way is using theNull-Coalescing-Operator
:((decimal)(decimalValue ?? 0 * 100)).ToString("N2")
This article from Jon Skeet is worth reading:
Decimal floating point in .NET (seach for keeping zeroes if you're impatient)
Solution 2
Since you using Nullable<T>
as your decimal
, Nullable<T>.ToString()
method doesn't have overloading takes parameters that you can use for formatting.
Instead of, you can explicitly cast it to decimal
and you can use .ToString()
method for formatting.
Just use "0.00"
format in your .ToString()
method.
decimal? decimalValue = .1211M;
string value = ((decimal)(decimalValue * 100)).ToString("0.00");
Console.WriteLine(value);
Output will be;
12.11
Here is a DEMO
.
As an alternative, you can use Nullable<T>.Value
without any conversation like;
string value = (decimalValue * 100).Value.ToString("0.00");
Check out for more information from Custom Numeric Format Strings
Solution 3
Alternatively, you can specify the format "F2", like so: string val = decVal.ToString("F2")
as this specifies 2 decimal places.
Solution 4
Use the fixed-point ("F) format specifier .
string value = (decimalValue * 100).ToString("F");
The default precision specifier is based on value of NumberFormatInfo.NumberDecimalDigits property which by default has value 2. So if don't specify a digit aftyer "F" , it by default specifies two decimal digits.
F0 - No decimal places
F1 - One decimal place
Solution 5
In case you do not want to limit to a certain amount of decimal digits:
decimal? decimalValue = .1211;
string value = decimalValue == null
? "0"
: decimalValue == 0
? "0"
: (decimalValue * 100).ToString().TrimEnd('0');
This will trim any (if any) trailing zeroes of the string and also return "0" if decimalValue
is null. If the value is 0 then "0" is returned without trimming.
Pushkar
Updated on March 20, 2020Comments
-
Pushkar about 4 years
I am facing a problem when I try to convert
decimal?
tostring
. Scenario isdecimal decimalValue = .1211; string value = (decimalValue * 100).ToString();
Current Result : value = 12.1100
Expected Result : value = 12.11
Please let me know, what could be reason for this.
-
Chris Sinclair about 11 yearsCasting to
decimal
will throw anInvalidOperationException
with this code, whereas Pushkar's original code would result in an empty string. Possibly not relevant in this case though. -
Chris Sinclair about 11 yearsCasting to
decimal
will throw anInvalidOperationException
with this code, whereas Pushkar's original code would result in an empty string. Possibly not relevant in this case though. -
Soner Gönül about 11 years@ChrisSinclair No, it will not throw any exception in this case.
-
Chris Sinclair about 11 yearsIt does when I run the code verbatim in LinqPad. EDIT: Shoot sorry, I meant for when
decimalValue
isnull
. Sorry, I forgot to actually write that. -
Chris Sinclair about 11 yearsSorry Tim, I meant it will throw when
decimalValue
isnull
. -
Chris Sinclair about 11 yearsSorry Soner, I forgot to write that that's for the
null
case whendecimalValue
is null. -
Emperor Orionii about 11 yearsThere is no need for cast and additional brackets,
Nullable<T>
has propertyValue
that would returnT
or in this casedecimal
. -
Soner Gönül about 11 years@EmperorOrionii Yeah, of course. That's another option also
;)
-
Pushkar about 11 yearsThanks for replying. I know, it can be solved by specifying the formatter but I want to know why toString() method is adding extra zero.
-
Tim Schmelter about 11 years@Pushkar: Have you read my quoted msdn link? "The scaling factor also preserves any trailing zeroes in a Decimal number....trailing zeroes can be revealed by the ToString method if an appropriate format string is applied" Your original decimal has 4 dcimal places, hence
ToString
reveals them. Btw, here's an explanation why it can be useful to remember the number of trailing zeros: stackoverflow.com/a/2996821/284240