numberConverter.lua 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. local numberConverter = {}
  2. local bit = require("bit")
  3. -- nic'd these from stack overflow
  4. -- https://stackoverflow.com/a/19996852
  5. function numberConverter.float2hex(n)
  6. if n == 0.0 then return 0.0 end
  7. local sign = 0
  8. if n < 0.0 then
  9. sign = 0x80
  10. n = -n
  11. end
  12. local mant, expo = math.frexp(n)
  13. local hext = {}
  14. if mant ~= mant then
  15. hext[#hext+1] = string.char(0xFF, 0x88, 0x00, 0x00)
  16. elseif mant == math.huge or expo > 0x80 then
  17. if sign == 0 then
  18. hext[#hext+1] = string.char(0x7F, 0x80, 0x00, 0x00)
  19. else
  20. hext[#hext+1] = string.char(0xFF, 0x80, 0x00, 0x00)
  21. end
  22. elseif (mant == 0.0 and expo == 0) or expo < -0x7E then
  23. hext[#hext+1] = string.char(sign, 0x00, 0x00, 0x00)
  24. else
  25. expo = expo + 0x7E
  26. mant = (mant * 2.0 - 1.0) * math.ldexp(0.5, 24)
  27. hext[#hext+1] = string.char(sign + math.floor(expo / 0x2),
  28. (expo % 0x2) * 0x80 + math.floor(mant / 0x10000),
  29. math.floor(mant / 0x100) % 0x100,
  30. mant % 0x100)
  31. end
  32. return tonumber(string.gsub(table.concat(hext),"(.)",
  33. function (c) return string.format("%02X%s",string.byte(c),"") end), 16)
  34. end
  35. -- nic'd these from stack overflow
  36. -- https://stackoverflow.com/a/19996852
  37. function numberConverter.hex2float(c)
  38. if c == 0 then return 0.0 end
  39. local c = string.gsub(string.format("%X", c),"(..)",function (x) return string.char(tonumber(x, 16)) end)
  40. local b1,b2,b3,b4 = string.byte(c, 1, 4)
  41. local sign = b1 > 0x7F
  42. local expo = (b1 % 0x80) * 0x2 + math.floor(b2 / 0x80)
  43. local mant = ((b2 % 0x80) * 0x100 + b3) * 0x100 + b4
  44. if sign then
  45. sign = -1
  46. else
  47. sign = 1
  48. end
  49. local n
  50. if mant == 0 and expo == 0 then
  51. n = sign * 0.0
  52. elseif expo == 0xFF then
  53. if mant == 0 then
  54. n = sign * math.huge
  55. else
  56. n = 0.0/0.0
  57. end
  58. else
  59. n = sign * math.ldexp(1.0 + mant / 0x800000, expo - 0x7F)
  60. end
  61. return n
  62. end
  63. function numberConverter.toNetworkFloat(f)
  64. local n = numberConverter.float2hex(f)
  65. return numberConverter.toNetworkInt(n)
  66. end
  67. function numberConverter.toNetworkInt(originalNumber)
  68. local byteA = bit.band(originalNumber,0xff)
  69. local byteB = bit.band(originalNumber,0xff00)
  70. byteB = bit.rshift(byteB,8)
  71. local byteC = bit.band(originalNumber,0xff0000)
  72. byteC = bit.rshift(byteC,16)
  73. local byteD = bit.band(originalNumber,0xff000000)
  74. byteD = bit.rshift(byteD,24)
  75. return (string.char(byteD) ..
  76. string.char(byteC) ..
  77. string.char(byteB) ..
  78. string.char(byteA))
  79. end
  80. function numberConverter.toNetworkNumber(originalNumber)
  81. local n = originalNumber
  82. if type(originalNumber) == "string" then
  83. n = tonumber(originalNumber)
  84. end
  85. if n == math.floor(n) then
  86. return numberConverter.toNetworkInt(n)
  87. else
  88. return numberConverter.toNetworkFloat(n)
  89. end
  90. end
  91. function numberConverter.intToLuaNumber(netNumString)
  92. local retval = 0
  93. local byteD = netNumString:sub(1,1):byte()
  94. local byteC = netNumString:sub(2,2):byte()
  95. local byteB = netNumString:sub(3,3):byte()
  96. local byteA = netNumString:sub(4,4):byte()
  97. retval = retval + byteA
  98. retval = retval + bit.lshift(byteB,8)
  99. retval = retval + bit.lshift(byteC,16)
  100. retval = retval + bit.lshift(byteD,24)
  101. return retval
  102. end
  103. function numberConverter.floatToLuaNumber(netNumString)
  104. local hexes = numberConverter.intToLuaNumber(netNumString)
  105. return numberConverter.hex2float(hexes)
  106. end
  107. return numberConverter