Bug in custom float sending function, need help debugging
3 replies, posted
There's a small bug in the float sending code of Overv's extended usermessages (which I modified somewhat). I already notified him, but since he's busy, I figured I'd ask here and save him some work.
Most of the time the float values arrive exactly as they were send, but there's a few times that they don't. For example:
-950.6402 arrived as -108.4897
88.0313 arrived as 41.4517
-9.7466 arrived as -1.2922
913.2517 arrived as 743.9090
The floats are encoded as chars, send, and parsed on the client. Code here:
Serverside:
[lua]
function umsg.ExtFloat( f )
f = f or 0
local neg = f < 0
f = math.abs( f )
-- Extract significant digits and exponent
local e = 0
if ( f >= 1 ) then
while ( f >= 1 ) do
f = f / 10
e = e + 1
end
elseif ( f != 0 ) then
while ( f < 0.1 ) do
f = f * 10
e = e - 1
end
end
-- Discard digits
local s = tonumber( string.sub( f, 3, 9 ) ) or 0
-- Negate if the original number was negative
if ( neg ) then s = -s end
-- Convert to unsigned
s = s + 8388608
-- Send significant digits as 3 byte number
local a = math.modf( s / 65536 ) s = s - a * 65536
local b = math.modf( s / 256 ) s = s - b * 256
local c = s
umsg.ExtChar( a - 128 )
umsg.ExtChar( b - 128 )
umsg.ExtChar( c - 128 )
-- Send exponent
umsg.ExtChar( e )
end
[/lua]
Clientside:
[lua]
function _R.bf_read:ExtReadFloat()
local a, b, c = self:ExtReadChar() + 128, self:ExtReadChar() + 128, self:ExtReadChar() + 128
local e = self:ExtReadChar()
local s = a * 65536 + b * 256 + c - 8388608
if ( s > 0 ) then
return tonumber( "0." .. s ) * 10^e
else
return tonumber( "-0." .. math.abs( s ) ) * 10^e
end
end
[/lua]
Is there a code guru here that spots the problem?
I'll rewrite the function today and then the issue should be gone.
use math.frexp and math.ldexp instead, it would work perfectly fine
Here's a patch for sending floats. I'm going to rewrite most of it now for more efficiency.
[lua]...
function umsg.Float( n )
local f, e = math.frexp( n or 0 )
f = math.Round( f * 2^24 )
e = math.Clamp( e, -128, 127 )
local t
for i = 16, 0, -8 do
t = math.modf( f / 2^i )
umsg.Char( t - 128 )
f = f - t * 2^i
end
umsg.Char( e )
end
...[/lua]
[lua]...
function _R.bf_read:ReadFloat()
local n1, n2, n3, e = self:ReadCharAbs(), self:ReadCharAbs(), self:ReadCharAbs(), self:ReadChar()
local f = ( n1 * 2^16 + n2 * 2^8 + n3 ) / 2^24
return math.ldexp( f, e )
end
...[/lua]
Sorry, you need to Log In to post a reply to this thread.