Reputation: 773
We need to insert decimal values into a XML document (done by a XML writer) which works fine. First we used XmlConvert.ToString(myDecimalValue)
which printed the value with four digits. Now we are forced to use always two digits and we tried to change this but with no luck so far.
First we dropped the use of XmlConvert
because we found not overload that allows us to format the decimal so we tried myDecimalValue.ToString("0.00")
which prints only two digits but replaces the .
with a ,
which is not valid in our case.
So how can we format a decimal like 25000.00m
to a string like 25000.00
? (Rounding does not matter because the values never have more then two digits set)
EDIT
decimal m_nAmt;
public decimal Amount
{
get
{
return m_nAmt;
}
set
{
if ((value < 0M) || (value > 999999999.99M))
{
throw new ArgumentOutOfRangeException();
}
if (SepaUtil.DecimalPlaces(value) > 2)
{
throw new ArgumentException();
}
m_nAmt = value;
}
}
And where is is written
// the original method
XmlConvert.ToString(m_nAmt);
Both methods are member of the same class;
Here is a example of a value written into the Xml file
<InstdAmt Ccy="EUR">3360.0000</InstdAmt>
Edit 2
A example where a node get written. I used the Immediate window to get the current value of the ControlSum
Property (System.Decimal) and the value written by XmlConvert
. The result is that XmlConvert
does write four decimal places although I cannot confirm that when using XmlConvert
with a decimal variable in LINQPad. Where one difference is that this library uses .net 2.0
My Conclusion & Solution
It seems that the XmlConvert.ToString()
or decimalvalue.ToString()
applies four decimal places because the original value had four 0
applied which got ignored by the SepaUtil.DecimalPlaces(value)
check (because 0
get ignored) and are not shown within the "Immediate Window" of VS2012. So I changed
m_nAmt = value;
to
m_nAmt = Math.Round(value,2);
to ensure always two decimal places. This way will add missing decimal places and truncate if there are more.
Upvotes: 2
Views: 6131
Reputation: 17288
Use
myValue.ToString("0.00", CultureInfo.InvariantCulture);
This will always write the value in a language-independent format (basically English). Use the same argument in any Parse()
or TryParse()
calls when reading.
As a general rule, all Parse()
, TryParse()
or ToString()
calls should have the CultureInfo argument specified, either as CultureInfo.InvariantCulture
or CultureInfo.CurrentCulture
. This prevents any strange bugs that happen when the users language uses a different decimal mark than the developers.
Upvotes: 5
Reputation: 1502816
Assuming this really is decimal
, I suggest you round the decimal value first:
decimal rounded = Math.Round(original, 2);
string roundedText = XmlConvert.ToString(rounded);
Obviously you can specify appropriate rounding/truncation behaviour, too.
While you can just specify the invariant culture instead as per PMF's answer, I would consider the above to be clearer in what you're trying to achieve:
One difference, however - in my version above, if the original number only has one decimal place (or none), you'll end up with (say) "15.5". If you explicitly format the string with the invariant culture, you'll end up with "15.50". If you definitely always want exactly 2 decimal places (no fewer) then PMF's answer is a more suitable one.
Upvotes: 3