WinBatch Tech Support Home

Database Search

If you can't find the information using the categories below, post a question over in our WinBatch Tech Support Forum.

TechHome

Number Conversion

Can't find the information you are looking for here? Then leave a message over on our WinBatch Tech Support Forum.

Single to Double Precision Floating Numbers and the Inverse

Keywords: 	 single double precision

This article is outdated. Use the new DataCast function found in WinBatch versions 2006B or newer.


Question:

I am trying to pass single precision floating point numbers to a third party(I didn't write it) DLL using DllCall. I know that the version of WinBatch I have doesn't directly support float parameters in DllCall. I tried the following to pass my SINGLE precision floats:

DLL entrypoint looks like this:

int function_name(float variable)
My WinBatch code looked like this:
value=4051.23
passvariable=BinaryAlloc(8)
BinaryPokeFlt(passvariable,0,value)
a1=DllCall(handle, long:"function_name", lpbinary:passvariable)
What actually gets passed is 0.0, or something like 2.536e-320 - i.e., it doesn't work.

However, I have been able to pass DOUBLE precision floating points using the following trick that I learned from the bulletin board:

value=4051.23
dummy=BinaryAlloc(8)
BinaryPokeFlt(dummy,0,value)
pass1=BinaryPeek4(dummy,0)
pass2=BinaryPeek4(dummy,4)
a1=DllCall(handle, long:"function_name", long:pass1, long:pass2)
This works when the DLL is expecting a double precision floating point value, i.e.
int function_name(double variable)
Can you think of a way to pass SINGLE precision floats similar to the way I did the double?

Is there an upgrade available to WinBatch that will allow this?

Answer:

I posted some code to do this very thing a month ago, maybe less. I see it didn't make it into the tech support database, so I'll repost it from my archive. Glad to hear someone might actually have a use for it ;-)

I took the code from the tech. help site for Single to Double and added the reverse. Then for fun I looked up Windows conversion to double check my work. It hasn't been extensively tested but it seems to work. I don't know if anyone else has a use for it though; I was just trying some funky API calls. DoubleToSingle does the same thing as DoubleToFloat, except the former does the conversion itself while the latter calls VarR4FromR8. I didn't bother with the FloatToDouble, but it would use VarR8FromR4.

:DoubleToSingle
;testnum input as double floating point value
;ans returned as single floating point value
bbds=BinaryAlloc(8)
BinaryPokeFlt(bbds, 0, testnum)
DL = BinaryPeek4(bbds,0)
DH = BinaryPeek4(bbds,4)
BinaryFree(bbds)
Dsign = abs(DH >> 31)
Ssign = Dsign << 31
Dexp = abs(DH >> 20 - (Dsign << 11))
Sexp = Dexp + 127 - 1023
Sexp = Sexp << 23
sfract = ((DH & 1048575) << 3) + (DL >> 28)
ans = Ssign | sexp | sfract
RETURN

:DoubleToFloat
;same as DoubleToSingle but uses windows conversion
db = BinaryAlloc(8)
BinaryPokeFlt(db, 0, testnum)
d1 = BinaryPeek4(db, 0)
d2 = BinaryPeek4(db, 4)
fb = BinaryAlloc(4)
Result = DllCall(OLEAUTDLL, long:"VarR4FromR8", long:d1, long:d2,
lpbinary:fb)
if result != 0 then message("VarR4FromR8 failed with error:" result)
BinaryEODSet(fb, 4)
ans = BinaryPeek4(fb, 0)
;message("varr4 says float is", temp)
BinaryFree(db)
BinaryFree(fb)
Return

:SingleToDouble
;testnum input as single floating point value
;ans returned as double floating point value

X80000000 = 1 << 32
X7F800000=255 << 23
X007FFFFF=8388607
Ssign =testnum & X80000000
Sexp =testnum & X7F800000
Sfract=testnum & X007FFFFF
Dexp=Sexp >> 23
Dexp=Dexp-127+1023
Dexp=Dexp << 20
SFH=Sfract >> 3
SFL=(Sfract & 7) << 29
DH=Ssign | Dexp | SFH
DL=SFL
bbsd = BinaryAlloc(8)
BinaryPoke4(bbsd,0,DL)
BinaryPoke4(bbsd,4,DH)
ans=BinaryPeekFlt(bbsd,0)
BinaryFree(bbsd)
RETURN

Article ID:   W14359
Filename:   Single to Double and the Reverse.txt
File Created: 2006:03:07:13:13:00
Last Updated: 2006:03:07:13:13:00