首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何让VB6用+infinity、-infinity和NaN初始化doubles?

如何让VB6用+infinity、-infinity和NaN初始化doubles?
EN

Stack Overflow用户
提问于 2009-05-20 03:18:40
回答 3查看 7.7K关注 0票数 9

VB6似乎没有那么容易将+infinity、-infinity和NaN存储到双变量中。如果可以的话,我可以在复数的上下文中与这些值进行比较,这将有所帮助。多么?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2009-05-22 04:04:10

一些不同的东西。正如您从Pax的示例中看到的,您实际上只需要查找IEEE754标准,然后将您的字节插入到正确的位置。我要给你的唯一的警告是MicroSoft has deprecated RtlMoveMemory,因为它可能会产生溢出类型的安全问题。作为另一种选择,您可以在“纯”VB中使用用户定义的类型和LSet进行一点小心的强制来完成此操作。(另请注意,有两种类型的NaN。)

代码语言:javascript
复制
Option Explicit

Public Enum abIEEE754SpecialValues
    abInfinityPos
    abInfinityNeg
    abNaNQuiet
    abNaNSignalling
    abDoubleMax
    abDoubleMin
End Enum

Private Type TypedDouble
    value As Double
End Type

Private Type ByteDouble
    value(7) As Byte
End Type

Public Sub Example()
    MsgBox GetIEEE754SpecialValue(abDoubleMax)
End Sub

Public Function GetIEEE754SpecialValue(ByVal value As abIEEE754SpecialValues) As Double
    Dim dblRtnVal As Double
    Select Case value
    Case abIEEE754SpecialValues.abInfinityPos
        dblRtnVal = BuildDouble(byt6:=240, byt7:=127)
    Case abIEEE754SpecialValues.abInfinityNeg
        dblRtnVal = BuildDouble(byt6:=240, byt7:=255)
    Case abIEEE754SpecialValues.abNaNQuiet
        dblRtnVal = BuildDouble(byt6:=255, byt7:=255)
    Case abIEEE754SpecialValues.abNaNSignalling
        dblRtnVal = BuildDouble(byt6:=248, byt7:=255)
    Case abIEEE754SpecialValues.abDoubleMax
        dblRtnVal = BuildDouble(255, 255, 255, 255, 255, 255, 239, 127)
    Case abIEEE754SpecialValues.abDoubleMin
        dblRtnVal = BuildDouble(255, 255, 255, 255, 255, 255, 239, 255)
    End Select
    GetIEEE754SpecialValue = dblRtnVal
End Function

Public Function BuildDouble( _
    Optional byt0 As Byte = 0, _
    Optional byt1 As Byte = 0, _
    Optional byt2 As Byte = 0, _
    Optional byt3 As Byte = 0, _
    Optional byt4 As Byte = 0, _
    Optional byt5 As Byte = 0, _
    Optional byt6 As Byte = 0, _
    Optional byt7 As Byte = 0 _
    ) As Double
    Dim bdTmp As ByteDouble, tdRtnVal As TypedDouble
    bdTmp.value(0) = byt0
    bdTmp.value(1) = byt1
    bdTmp.value(2) = byt2
    bdTmp.value(3) = byt3
    bdTmp.value(4) = byt4
    bdTmp.value(5) = byt5
    bdTmp.value(6) = byt6
    bdTmp.value(7) = byt7
    LSet tdRtnVal = bdTmp
    BuildDouble = tdRtnVal.value
End Function

最后一点需要注意的是,您也可以通过这种方式获取NaN:

代码语言:javascript
复制
Public Function GetNaN() As Double
    On Error Resume Next
    GetNaN = 0 / 0
End Function
票数 14
EN

Stack Overflow用户

发布于 2009-05-20 04:37:27

实际上,有一个更简单的方法来获得无穷大,-Infinity,而不是一个数字:

代码语言:javascript
复制
public lfNaN    as Double ' or As Single
public lfPosInf as Double
public lfNegInf as Double

on error resume next    ' to ignore Run-time error '6': Overflow and '11': Division by zero
lfNaN    =  0 / 0       ' -1.#IND
lfPosInf =  1 / 0       '  1.#INF
lfNegInf = -1 / 0       ' -1.#INF

on error goto 0         ' optional to reset the error handler
票数 20
EN

Stack Overflow用户

发布于 2009-05-20 03:34:21

This page展示了一种稍微有点折磨人的方式。我已经削减了它,以符合您的问题,但没有彻底测试。如果有什么问题,请告诉我。我在那个网站上注意到的一件事是,他们有一个安静的NaN的代码是错误的,它应该以1位开始尾数-他们似乎把这与信号NaN混淆了。

代码语言:javascript
复制
Public NegInfinity As Double
Public PosInfinity As Double
Public QuietNAN As Double

Private Declare Sub CopyMemoryWrite Lib "kernel32" Alias "RtlMoveMemory" ( _
    ByVal Destination As Long, source As Any, ByVal Length As Long)

' IEEE754 doubles:                                                          '
'   seeeeeee eeeemmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm '
'   s = sign                                                                '
'   e = exponent                                                            '
'   m = mantissa                                                            '
'   Quiet NaN: s = x, e = all 1s, m = 1xxx...                               '
'   +Inf     : s = 0, e = all 1s, m = all 0s.                               '
'   -Inf     : s = 1, e = all 1s, m = all 0s.                               '
代码语言:javascript
复制
Public Sub Init()
    Dim ptrToDouble As Long
    Dim byteArray(7) As Byte
    Dim i As Integer

    byteArray(7) = &H7F
    For i = 0 To 6
        byteArray(i) = &HFF
    Next
    ptrToDouble = VarPtr(QuietNAN)
    CopyMemoryWrite ptrToDouble, byteArray(0), 8

    byteArray(7) = &H7F
    byteArray(6) = &HF0
    For i = 0 To 5
        byteArray(i) = 0
    Next
    ptrToDouble = VarPtr(PosInfinity)
    CopyMemoryWrite ptrToDouble, byteArray(0), 8

    byteArray(7) = &HFF
    byteArray(6) = &HF0
    For i = 0 To 5
        byteArray(i) = 0
    Next
    ptrToDouble = VarPtr(NegInfinity)
    CopyMemoryWrite ptrToDouble, byteArray(0), 8
End Sub

它基本上使用内核级内存拷贝来将位模式从字节数组转移到双精度数组。

然而,你应该记住,有多个位值可以表示QNaN,特别是符号位可以是0或1,尾数中除第一位以外的所有位也可以是0或1。这可能会使您的比较策略复杂化,除非您可以发现VB6是否只使用其中一个位模式-但是,假设VB6正确地实现了IEE754双精度,这不会影响这些值的初始化。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/885994

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档