2

我们有一个 .net visual basic 项目,该项目使用Strings.formatnumberthis 所使用的函数,因为它具有灵活性,即动态变量允许的小数位数。但是我遇到了一个令人讨厌的错误,因为此函数似乎将所有内容四舍五入为 15 位

所以

?  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

所以两个问题

  • 为什么这个函数会这样做?
  • 是否有我们可以使用的 .net 函数将字符串转换为数字并返回一个字符串,并且小数位数可以是动态的?
4

4 回答 4

2

double被定义为具有 15-16 位精度。

您可能需要改用十进制,它提供 28 位数字。

添加了十进制精度的 VB.Net 链接

于 2013-09-03T15:36:54.280 回答
2

双精度定义为 15-16 位精度。

改用十进制

十进制关键字表示 128 位数据类型。与浮点类型相比,十进制类型的精度更高,范围更小,适用于金融和货币计算。小数类型的大致范围和精度如下表所示。

于 2013-09-03T15:36:55.157 回答
1

是否有我们可以使用的 .net 函数将字符串转换为数字并返回一个字符串,并且小数位数可以是动态的?

这是 FormatNumber 方法的一个简单包装器,它允许您指定最大长度以及整数部分的填充、小数位、千位分隔符和负括号:

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

像这样称呼它:

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

输出是:

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

这假设您将字符串验证为数字类型。如果没有,您可以改用 TryParse 方法。

于 2013-09-04T01:50:50.803 回答
0

double精度只有 15–16位十进制数字。虽然可以有更多的数字,但它们大多是垃圾。如果您愿意,某些语言/环境会选择向您显示完整的数字,但这没什么用,因为所有这些数字都没有意义;它们在计算中不可靠,并不像你期望的数字那样表现,等等。它们本质上是二进制到十进制转换的产物。因此,.NET 会自动舍入到 double 的小数精度以进行显示。它不会欺骗您认为该数字比实际更精确。

请注意,在某些情况下您希望显示这些数字(例如,当向某人展示后面确实有 50 个数字时),但这在 .NET 中是不可能的。

于 2013-09-04T04:55:24.797 回答