I have the need to format a decimal number as currency but I do not wish for any rounding to occur in the process.
For example (example culture is en-US)
Dim money = 1234.556789D
money.ToString("C") ' Yields $1,234.56 (notice the rounding & truncating)
money.ToString("C99") ' Yields $1,234.556789000000000000....0 -- close but not perfect, those trailing zeros are unwanted.
' I want something that would result in this...
money.ToString("??") ' Yields $1,234.56789
' likewise....
money = 0.1D
money.ToString("??") ' Yields $0.10 (notice that it at least matches the culture's currency format -- two decimal places)
Assuming all of the users of this application would be using en_US rules I could make that "??" be something hard-coded like "$#,##0.00################################################################" -- but that makes my stomach churn. Is there a built-in way to accomplish what I'm after?
You could do something like this...
var money = 1234.556789D;
Console.WriteLine(money.ToString(GetFormat(money)));
money = .1D;
Console.WriteLine(money.ToString(GetFormat(money)));
using the following method to get the format string...
static string GetFormat(double input)
{
// get the number of decimal places to show
int length = input.ToString().Length - input.ToString().IndexOf(".") - 1;
// return the currency format string to use with decimal.ToString()
return string.Format("C{0}", length < 2 ? 2 : length);
}
If you wanted to take it a step further, you could also wrap all of this into an extension method so that you didn't have to call the GetFormat() method from inside ToString() - that might make things look a bit cleaner.
ToString("C20") -- C takes a precision suffix
EDIT: oops, didn't read the question apparently.
.ToString("C20").Trim('0') seems like the fix, but this doesn't work when you're using string.Format...
Seeing that there doesn't seem to be a built-in way of doing this, I ended up rolling my own extension method that looks like...
Public Function ToUnroundedCurrency(ByVal value As Decimal) As String
Dim valueAsString As String = value.ToString() ' Some loss of precision happens here, but it is not a concern.
Dim decimalLocation As Integer = valueAsString.IndexOf(".")
' Get number of digits after the decimal place in the number
Dim numberOfDecimalPlaces As Integer = 0
If (decimalLocation > 0) Then numberOfDecimalPlaces = valueAsString.Length - decimalLocation - 1
' The currency formatter has a limit of 99 decimal places -- due to the decimal -> ToString() conversion above, this will never happen, but being defensive anyway.
If (numberOfDecimalPlaces > 99) Then
numberOfDecimalPlaces = 99
ElseIf (numberOfDecimalPlaces < CultureInfo.CurrentCulture.NumberFormat.CurrencyDecimalDigits) Then
' also make sure we at least have the minimum required decimal places
numberOfDecimalPlaces = CultureInfo.CurrentCulture.NumberFormat.CurrencyDecimalDigits
End If
Return value.ToString("C" & numberOfDecimalPlaces)
End Function
I noted some negligible loss of precision. We (or anybody probably) wouldn't be dealing with decimal values fractional enough enough to ever run into the limitations.
Yes. Here's the answer from another forum:
You could try writing a regular expression to get rid of all of those trailing 0's.
来源:https://stackoverflow.com/questions/1180068/format-currency-without-rounding