0

我尝试了等效的Michael Meadows EDIT 2,但在 VB.NET 中得到了不同的结果。(具体来说,DoubleDecimal结果都是 600000.0238418580。)

我已经确定差异在于Single存储到 a 中的除法的编译时准确性Single以及当您强制除法在运行时发生时。

因此,THREE_FIFTHSvTHREE_FIFTHSasDecimal求和提供不同的结果:

const ONE_MILLION As Integer = 1000000

Dim THREEsng As Single = 3!
Dim FIVEsng As Single = 5!
Dim vTHREE_FIFTHS As Single = THREEsng / FIVEsng

const THREE_FIFTHS As Single = 3! / 5!

Console.WriteLine("Three Fifths: {0}", THREE_FIFTHS.ToString("F10"))
Dim asSingle As Single = 0!
Dim asDouble As Double = 0#
Dim asDecimal As Decimal = 0@

For i As Integer = 1 To ONE_MILLION
    asSingle += CSng(THREE_FIFTHS)
    asDouble += CDbl(THREE_FIFTHS)
    asDecimal += CDec(THREE_FIFTHS)
Next
Console.WriteLine("Six Hundred Thousand: {0:F10}", THREE_FIFTHS * ONE_MILLION)
Console.WriteLine("Single: {0}", asSingle.ToString("F10"))
Console.WriteLine("Double: {0}", asDouble.ToString("F10"))
Console.WriteLine("Decimal: {0}", asDecimal.ToString("F10"))

Console.WriteLine("vThree Fifths: {0}", vTHREE_FIFTHS.ToString("F10"))
asSingle = 0!
asDouble = 0#
asDecimal = 0@

For i As Integer = 1 To ONE_MILLION
    asSingle += CSng(vTHREE_FIFTHS)
    asDouble += CDbl(vTHREE_FIFTHS)
    asDecimal += CDec(vTHREE_FIFTHS)
Next
Console.WriteLine("Six Hundred Thousand: {0:F10}", vTHREE_FIFTHS * ONE_MILLION)
Console.WriteLine("Single: {0}", asSingle.ToString("F10"))
Console.WriteLine("Double: {0}", asDouble.ToString("F10"))
Console.WriteLine("Decimal: {0}", asDecimal.ToString("F10"))

突出显示差异的结果是:

Three Fifths: 0.6000000000
Six Hundred Thousand: 600000.0000000000
Single: 599093.4000000000
Double: 600000.0238418580
Decimal: 600000.0238418580
vThree Fifths: 0.6000000000
Six Hundred Thousand: 600000.0000000000
Single: 599093.4000000000
Double: 600000.0238418580
Decimal: 600000.0000000000

我的问题是,你能让 VB.NET 得到一个Const Single与运行时结果等效的表达式吗?(即产生THREE_FIFTHS与 相同的结果vTHREE_FIFTHS。)

4

1 回答 1

0

看起来答案是“无法完成”,正如我在对 C# 的类似问题的回答中指出的那样,编译时常量并不是真正的常量,而是在每个使用上下文中重新解释(并且与C#)。具体来说,CDec编译时转换会产生与运行时等效的结果不同的结果。

Sub Main
        const ONE_MILLION As Integer = 1000000

        Dim THREEsng As Single = 3!
        Dim FIVEsng As Single = 5!
        Dim vTHREE_FIFTHS As Single = THREEsng / FIVEsng

        const THREE_FIFTHS As Single = 3! / 5!

        Console.WriteLine("Three Fifths: {0}", THREE_FIFTHS.ToString("F10"))
        Console.WriteLine(GetByteString(THREE_FIFTHS))
        Dim asSingle As Single = 0!
        Dim asDouble As Double = 0#
        Dim asDecimal As Decimal = 0@

        For i As Integer = 1 To ONE_MILLION
            asSingle += CSng(THREE_FIFTHS)
            asDouble += CDbl(THREE_FIFTHS)
            asDecimal += CDec(THREE_FIFTHS)
        Next
        Console.WriteLine("Six Hundred Thousand: {0:F10}", THREE_FIFTHS * ONE_MILLION)
        Console.WriteLine("Single: {0}", asSingle.ToString("F10"))
        Console.WriteLine("Double: {0}", asDouble.ToString("F10"))
        Console.WriteLine("Decimal: {0}", asDecimal.ToString("F10"))
        Console.WriteLine(GetByteString(CSng(THREE_FIFTHS)))
        Console.WriteLine(GetByteString(CDbl(THREE_FIFTHS)))
        Console.WriteLine(GetByteString(CDec(THREE_FIFTHS)))

        Console.WriteLine("vThree Fifths: {0}", vTHREE_FIFTHS.ToString("F10"))
        Console.WriteLine(GetByteString(vTHREE_FIFTHS))
        asSingle = 0!
        asDouble = 0#
        asDecimal = 0@

        For i As Integer = 1 To ONE_MILLION
            asSingle += CSng(vTHREE_FIFTHS)
            asDouble += CDbl(vTHREE_FIFTHS)
            asDecimal += CDec(vTHREE_FIFTHS)
        Next
        Console.WriteLine("Six Hundred Thousand: {0:F10}", vTHREE_FIFTHS * ONE_MILLION)
        Console.WriteLine("Single: {0}", asSingle.ToString("F10"))
        Console.WriteLine("Double: {0}", asDouble.ToString("F10"))
        Console.WriteLine("Decimal: {0}", asDecimal.ToString("F10"))
        Console.WriteLine(GetByteString(CSng(vTHREE_FIFTHS)))
        Console.WriteLine(GetByteString(CDbl(vTHREE_FIFTHS)))
        Console.WriteLine(GetByteString(CDec(vTHREE_FIFTHS)))

End Sub

' Define other methods and classes here
Function GetByteString(d As Double) As String

    return "#" & string.Join("", BitConverter.GetBytes(d) _
             .Select(Function (b)b.ToString("X2")))

End Function

Function GetByteString(d As Decimal) As String

    return "D" & string.Join("", Decimal.GetBits(d) _
            .Select(Function (b)b.ToString("X8")))

End Function

Function GetByteString(f As Single) As String

    return "S" & string.Join("", BitConverter.GetBytes(f) _
            .Select(Function (b)b.ToString("X2")))

End Function

输出:

Three Fifths: 0.6000000000
S9A99193F
Six Hundred Thousand: 600000.0000000000
Single: 599093.4000000000
Double: 600000.0238418580
Decimal: 600000.0238418580
S9A99193F
#000000403333E33F
D64494C42000221B200000000000F0000
vThree Fifths: 0.6000000000
S9A99193F
Six Hundred Thousand: 600000.0000000000
Single: 599093.4000000000
Double: 600000.0238418580
Decimal: 600000.0000000000
S9A99193F
#000000403333E33F
D00000006000000000000000000010000

于 2013-10-25T17:30:00.190 回答