Bug in custom float sending function, need help debugging

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]