VB6 no parece que sea tan fácil almacenar + infinity, -infinity y NaN en doble vars. Ayudaría si pudiera, de modo que pudiera hacer comparaciones con esos valores en el contexto de números complejos. ¿Cómo?¿Cómo se obtiene VB6 para inicializar los dobles con + infinito, -infinito y NaN?
Respuesta
Un par de cosas diferentes. Como puede ver en el ejemplo de Pax, solo necesita buscar el estándar IEEE 754 y luego conectar sus bytes en los lugares correctos. La única precaución que le daría es que MicroSoft has deprecated RtlMoveMemory debido a su potencial para crear problemas de seguridad del tipo de desbordamiento. Como alternativa puede lograr esto en VB "puro" con un poco de coerción cuidadosa usando Tipos definidos por el usuario y LSet. (Tenga en cuenta también que hay dos tipos de NaN.)
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
Una última nota al margen, también se puede obtener NaN de esta manera:
Public Function GetNaN() As Double
On Error Resume Next
GetNaN = 0/0
End Function
This page muestra una forma ligeramente tortuosa de hacerlo. Lo recorté para que coincida con lo que pidió su pregunta, pero no lo he probado a fondo. Avíseme si hay algún problema. Una cosa que noté en ese sitio es que el código que tenían para un NaN silencioso era incorrecto, debería comenzar la mantisa con un bit de 1 bit, parecían haberse confundido con un NaN de señalización.
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. '
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
Se utiliza básicamente copias de la memoria a nivel de kernel para transferir los patrones de bits a partir de una matriz de bytes en el doble.
Usted debe tener en cuenta sin embargo que hay bits valores múltiples que pueden representar QNAN, específicamente el bit de signo puede ser 0 o 1 y todos los bits de la mantisa que no sea el primero también puede ser cero o 1. Esto puede complicar su estrategia para las comparaciones a menos que pueda descubrir si VB6 solo usa uno de los patrones de bits; sin embargo, no afectará la inicialización de esos valores, suponiendo que VB6 implemente correctamente el IEE754 se duplica.
Así que va a asociar al blog de la questionner original, donde él publicó una entrada con su mejor puñalada un día antes de hacer la pregunta? ¡Bastante, es divertido! – MarkJ
Eso no es solo divertido, es gracioso. En realidad, no sabía que el que preguntaba era el propietario de ese blog en ese momento, pero hay su apodo de stackoverflow allí mismo en el blog :-) No estoy seguro de si eliminar esta respuesta o no. Si nada más, puede proporcionar algo de diversión a los demás. – paxdiablo
No estoy seguro de si reír o avergonzarme. – bugmagnet
En realidad, hay una manera mucho más simple para obtener Infinity, -Infinity y no un número:
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
+1 ¡Nunca lo había sabido antes! ¿Parece que también puedes obtener NAN al evaluar 0/0? De todos modos, Debug.Print dice que es -1. # IND que es diferente del 1. # INF que obtengo de 1/0. Supongo que es NAN. – MarkJ
+1 Eso es simplemente impresionante –
'Debug.Print -lfNaN' da' 1. # QNAN', que supongo que es el NaN "silencioso" (?). – Andre
- 1. ¿Cómo creo o pruebo para NaN o infinito en Perl?
- 2. Hasta el infinito y volver
- 3. Utilización de un desplazamiento infinito/infinito
- 4. pergamino infinito liviano con backbone.js
- 5. Hasta el infinito y más allá en VBA
- 6. símbolo de infinito con HTML
- 7. isótopo y Desplazamiento infinito con activación manual
- 8. constante de infinito de glsl
- 9. Javascript bucle infinito con defineSetter
- 10. Predicado Prólogo - bucle infinito
- 11. ¿Cómo se comparan los valores arbitrarios de coma flotante con el infinito?
- 12. C# flotan bucle infinito
- 13. Código scala loop infinito
- 14. Desplazamiento horizontal infinito UIScrollView
- 15. jQuery desplazamiento infinito "reset"
- 16. ¿Cómo se divide un infinito para el bucle (;;) en C?
- 17. Desplazamiento infinito en django
- 18. bucle infinito en C++
- 19. Jugar con el infinito: aritméticos vagos
- 20. Jquery - bucle infinito
- 21. Android looping infinito ListView?
- 22. Mejor bucle infinito
- 23. Infinito negativo en Lisp
- 24. Numpy: utilice contenedores con un rango infinito
- 25. Desplazamiento infinito y la devolución de llamada
- 26. bucle infinito en java.util.HashMap
- 27. desplazamiento infinito disparador manual
- 28. try/catch con InputMismatchException crea bucle infinito
- 29. Infinito Contando Loop en Brainfuck
- 30. raspar sitios web con desplazamiento infinito
Esto es increíblemente genial. Muchas gracias por compartirlo. – bugmagnet