Mike
Mike

Reputation: 6050

strings.formatnumber is limiting to 15 characters?

We have a .net visual basic project that uses the function Strings.formatnumber this is used because of its flexibility, namely the number of decimal places allowed with a dynamic variable. However I have come across a nasty bug in that this function seems to round everything to 15 digits

so

?  Strings.FormatNumber("123456789012345.66", 2,Microsoft.VisualBasic.TriState.True,Microsoft.VisualBasic.TriState.False,Microsoft.VisualBasic.TriState.False)
Results 123456789012345.00

?  Strings.FormatNumber("12345678901234.66", 2,Microsoft.VisualBasic.TriState.True,Microsoft.VisualBasic.TriState.False,Microsoft.VisualBasic.TriState.False)
Results 12345678901234.60

?  Strings.FormatNumber("1234567890123.66", 2,Microsoft.VisualBasic.TriState.True,Microsoft.VisualBasic.TriState.False,Microsoft.VisualBasic.TriState.False)
Results 1234567890123.66

?  Strings.FormatNumber("1234567890123456666.66", 2,Microsoft.VisualBasic.TriState.True,Microsoft.VisualBasic.TriState.False,Microsoft.VisualBasic.TriState.False)
Results 1234567890123460000.00

So two questions

Upvotes: 2

Views: 544

Answers (4)

tinstaafl
tinstaafl

Reputation: 6948

Is there a .net function that we can use that will turn strings into numbers and return a string and where the number of decimals can be dynamic?

Here's a simple wrapper for the FormatNumber method that allows you to specify, the maximum length with padding for integral portion, decimal places, thousands separator and negative parentheses:

Private Function MyFormatNumber(input As String, MaxLength As Integer, Optional RightDecimal As Integer = 2, Optional Thousands As TriState = TriState.UseDefault, Optional Negative As TriState = TriState.UseDefault) As String
    Dim TempNumber As Decimal = Decimal.Parse(input)
    Dim DecimalIndex As Integer = Decimal.Truncate(Math.Abs(TempNumber)).ToString.Length
    Dim LeftPad As Integer = (MaxLength - RightDecimal) - DecimalIndex
    MyFormatNumber = Strings.FormatNumber(TempNumber, RightDecimal, TriState.True, Negative, Thousands)
    If MyFormatNumber.StartsWith("(") Then
        MyFormatNumber = "(" + MyFormatNumber.Substring(1).PadLeft((MyFormatNumber.Length - 1) + LeftPad, "0"c)
    Else
        MyFormatNumber = MyFormatNumber.PadLeft(MyFormatNumber.Length + LeftPad, "0"c)
    End If
End Function

Call it like this:

Dim numberstr As String = ("-12345678901234566.12347", 22, 4, TriState.True, TriState.True)

The output is:

?numberstr
"(012,345,678,901,234,566.1235)"

This assumes that you are validating the strings to be a number type. If not you can use the TryParse method instead.

Upvotes: 1

Joey
Joey

Reputation: 354734

double only has 15–16 decimal digits of precision. While there can be more digits, they are mostly garbage. Some languages/environments opt to show you the complete number if you want to, but that's of little use because all those digits aren't meaningful; they're unreliable in calculations, don't really behave like you would expect numbers to do, etc. They are artifacts of conversion of binary to decimal, essentially. .NET therefore rounds to double's decimal precision automatically for display purposes. It doesn't deceive you into thinking that the number is more precise than it actually is.

Mind you, there are instances when you want those digits to be displayed (e.g. when demonstrating to someone that there's really 50 digits following), but that's not possible in .NET.

Upvotes: 0

Rahul Tripathi
Rahul Tripathi

Reputation: 172558

Double is defined with 15-16 digit precision.

Try Decimal instead.

The decimal keyword indicates a 128-bit data type. Compared to floating-point types, the decimal type has more precision and a smaller range, which makes it appropriate for financial and monetary calculations. The approximate range and precision for the decimal type are shown in the following table.

Upvotes: 2

devio
devio

Reputation: 37215

double is defined as having 15-16 digits precision.

You may need to use decimal instead, which offers 28 digits.

Added VB.Net links for decimal and double

Upvotes: 2

Related Questions