私はLuaで浮動小数点から16進数への変換に苦労しています。私のアプリケーションは古いAkai S2000サンプラーと通信します。サンプラーは、2バイトのメッセージを4つのニブル値にコーディングします。ニブルは逆順になっているため、最も重要なニブルは最後です。値の小数部の2進符号化を使用する1つのパラメータがあります。 2つのMSニブルは値の整数部分を符号化するために使用され、LSニブルは2進小数部分を符号化するために使用される。浮動小数点値を16進数に変換する
このディスカッションに基づいてhttps://bytes.com/topic/c/answers/219928-how-convert-float-hex私は与えられたパラメータ値からこれらのニブル値を生成するためにLuaアルゴリズムを実装し始めました。私はビット計算でそれほど強くないので、私は間違った方法で多くのことをやっていると思う。これらの値を計算し、私の愚かなif/elseハックを避けるためのより簡単な方法があるはずです。
マイナスの数字に対しては(下に貼り付けた)自分のコードは機能しますが、負の数値は非常に難しくなります。
私のテストでは、期待値のテーブルに追加しました。各テーブルは次のように動作します。
key = give value * 100
value = expected outcome from my algorithm
Ie. positiveNumbersテーブルの最初のエントリは0.01の入力値を表し、その値の期待される出力は02 00 00 00を含む4バイトのMemoryBlockです(最初の2バイトは端数を表し、最後の2バイトは整数部分を表します)。
現在、私のアルゴリズムは-0.94で失敗し、他の値を壊さずにハックすることはできません。
ビット計算の文字列があり、特に負の値を変換したときに起こったnoobの間違いを簡単に見ることができる人はいますか? 助けや指導をいただければ幸いです!
のLuaコード:あなたが持っている
function float2nibbles(value)
local nibbles = MemoryBlock(4, true)
-- Retreive integral and fraction parts of the given value to be converted
local integ, fract = math.modf(math.abs(value))
-- Calculate the values of the integral part (last two nibbles)
local bi = BigInteger(integ)
if value < 0 then
-- This variable is sometimes added in the negative conversion of the MS nibbles
local lsAdd = 1
if integ == 0 then
lsAdd = 0
end
nibbles:setByte(2, bit.band(bit.bnot(bi:getBitRangeAsInt(0,4)) + lsAdd, 0xF))
nibbles:setByte(3, bit.band(bit.bnot(bi:getBitRangeAsInt(4,4)), 0xF))
else
nibbles:setByte(2, bit.band(bi:getBitRangeAsInt(0,4), 0xF))
nibbles:setByte(3, bit.band(bi:getBitRangeAsInt(4,4), 0xF))
end
-- Calculate the values of the fraction (first two nibbles)
local remainder = fract
local prevRemain = 0
for i = 1,2 do
remainder = remainder * 16
-- Integral part of the remainder
local d = math.modf(remainder)
if value < 0 and fract ~= 0 then
local lsAdd = 1
if fract == 0 or i == 1 then
lsAdd = 0
end
console(string.format("lsAdd %d", lsAdd))
nibbles:setByte(2 - i, bit.band(bit.bnot(d) + lsAdd, 0xF))
else
nibbles:setByte(2 - i, bit.band(d, 0xF))
end
console(string.format("fract %d = %d, %.2f", i, d, remainder))
prevRemain = remainder
remainder = remainder - d
end
-- For some reason this increment helps when the LS nibble should increment the value of the second nibble
if nibbles:getByte(0) == 0 and nibbles:getByte(1) ~= 0 and value < 0 then
console(string.format("weird increment { %d %d }", nibbles:getByte(0), nibbles:getByte(1)))
nibbles:setByte(1, nibbles:getByte(1) + 1)
end
-- The precision of this data is one byte but apparently they seem to use a third increment to check for rounding
remainder = remainder * 16
console(string.format("final remainder %.2f", remainder))
if math.abs(remainder - prevRemain) > 0.001 and remainder > 14 then
console(string.format("overflow -> %.2f (%.2f)", remainder, prevRemain))
if value < 0 then
nibbles:setByte(0, nibbles:getByte(0) - 1)
else
nibbles:setByte(0, nibbles:getByte(0) + 1)
end
end
console(string.format("%.2f : integral part %s (%s), fract %.2f", value, bit.tohex(integ, 2), nibbles:toHexString(1), fract))
return nibbles
end
local positiveNumbers = {
"02 00 00 00",
"05 00 00 00",
"07 00 00 00",
"0A 00 00 00",
"0C 00 00 00",
"0F 00 00 00",
"02 01 00 00",
"04 01 00 00",
"07 01 00 00",
"09 01 00 00",
"0C 01 00 00",
"0E 01 00 00",
"01 02 00 00",
"03 02 00 00",
"06 02 00 00",
"09 02 00 00",
"0B 02 00 00",
"0E 02 00 00",
"00 03 00 00",
"03 03 00 00",
"05 03 00 00",
"08 03 00 00",
"0B 03 00 00",
"0D 03 00 00",
"00 04 00 00",
"02 04 00 00",
"05 04 00 00",
"07 04 00 00",
"0A 04 00 00",
"0C 04 00 00",
"0F 04 00 00",
"02 05 00 00",
"04 05 00 00",
"07 05 00 00",
"09 05 00 00",
"0C 05 00 00",
"0E 05 00 00",
"01 06 00 00",
"03 06 00 00",
"06 06 00 00",
"09 06 00 00",
"0B 06 00 00",
"0E 06 00 00",
"00 07 00 00",
"03 07 00 00",
"05 07 00 00",
"08 07 00 00",
"0B 07 00 00",
"0D 07 00 00",
"00 08 00 00",
"02 08 00 00",
"05 08 00 00",
"07 08 00 00",
"0A 08 00 00",
"0C 08 00 00",
"0F 08 00 00",
"02 09 00 00",
"04 09 00 00",
"07 09 00 00",
"09 09 00 00",
"0C 09 00 00",
"0E 09 00 00",
"01 0A 00 00",
"03 0A 00 00",
"06 0A 00 00",
"09 0A 00 00",
"0B 0A 00 00",
"0E 0A 00 00",
"00 0B 00 00",
"03 0B 00 00",
"05 0B 00 00",
"08 0B 00 00",
"0B 0B 00 00",
"0D 0B 00 00",
"00 0C 00 00",
"02 0C 00 00",
"05 0C 00 00",
"07 0C 00 00",
"0A 0C 00 00",
"0C 0C 00 00",
"0F 0C 00 00",
"02 0D 00 00",
"04 0D 00 00",
"07 0D 00 00",
"09 0D 00 00",
"0C 0D 00 00",
"0E 0D 00 00",
"01 0E 00 00",
"03 0E 00 00",
"06 0E 00 00",
"09 0E 00 00",
"0B 0E 00 00",
"0E 0E 00 00",
"00 0F 00 00",
"03 0F 00 00",
"05 0F 00 00",
"08 0F 00 00",
"0B 0F 00 00",
"0D 0F 00 00",
"00 00 01 00"
}
local negativeNumbers = {
"0E 0F 0F 0F",
"0B 0F 0F 0F",
"09 0F 0F 0F",
"06 0F 0F 0F",
"04 0F 0F 0F",
"01 0F 0F 0F",
"0E 0E 0F 0F",
"0C 0E 0F 0F",
"09 0E 0F 0F",
"07 0E 0F 0F",
"04 0E 0F 0F",
"02 0E 0F 0F",
"0F 0D 0F 0F",
"0D 0D 0F 0F",
"0A 0D 0F 0F",
"07 0D 0F 0F",
"05 0D 0F 0F",
"02 0D 0F 0F",
"00 0D 0F 0F",
"0D 0C 0F 0F",
"0B 0C 0F 0F",
"08 0C 0F 0F",
"05 0C 0F 0F",
"03 0C 0F 0F",
"00 0C 0F 0F",
"0E 0B 0F 0F",
"0B 0B 0F 0F",
"09 0B 0F 0F",
"06 0B 0F 0F",
"04 0B 0F 0F",
"01 0B 0F 0F",
"0E 0A 0F 0F",
"0C 0A 0F 0F",
"09 0A 0F 0F",
"07 0A 0F 0F",
"04 0A 0F 0F",
"02 0A 0F 0F",
"0F 09 0F 0F",
"0D 09 0F 0F",
"0A 09 0F 0F",
"07 09 0F 0F",
"05 09 0F 0F",
"02 09 0F 0F",
"00 09 0F 0F",
"0D 08 0F 0F",
"0B 08 0F 0F",
"08 08 0F 0F",
"05 08 0F 0F",
"03 08 0F 0F",
"00 08 0F 0F",
"0E 07 0F 0F",
"0B 07 0F 0F",
"09 07 0F 0F",
"06 07 0F 0F",
"04 07 0F 0F",
"01 07 0F 0F",
"0E 06 0F 0F",
"0C 06 0F 0F",
"09 06 0F 0F",
"07 06 0F 0F",
"04 06 0F 0F",
"02 06 0F 0F",
"0F 05 0F 0F",
"0D 05 0F 0F",
"0A 05 0F 0F",
"07 05 0F 0F",
"05 05 0F 0F",
"02 05 0F 0F",
"00 05 0F 0F",
"0D 04 0F 0F",
"0B 04 0F 0F",
"08 04 0F 0F",
"05 04 0F 0F",
"03 04 0F 0F",
"00 04 0F 0F",
"0E 03 0F 0F",
"0B 03 0F 0F",
"09 03 0F 0F",
"06 03 0F 0F",
"04 03 0F 0F",
"01 03 0F 0F",
"0E 02 0F 0F",
"0C 02 0F 0F",
"09 02 0F 0F",
"07 02 0F 0F",
"04 02 0F 0F",
"02 02 0F 0F",
"0F 01 0F 0F",
"0D 01 0F 0F",
"0A 01 0F 0F",
"07 01 0F 0F",
"05 01 0F 0F",
"02 01 0F 0F",
"00 01 0F 0F",
"0D 00 0F 0F",
"0B 00 0F 0F",
"08 00 0F 0F",
"05 00 0F 0F",
"03 00 0F 0F",
"00 00 0F 0F"
}
function verifyFloat2Nibbles(value, expectedMemBlock)
local temp = string.upper(float2nibbles(value):toHexString(1))
assert(expectedMemBlock == temp,
string.format("Incorrect result for %.2f, expected %s, got %s", value, expectedMemBlock, temp))
end
for k,v in pairs(positiveNumbers) do
verifyFloat2Nibbles(k/100, v)
end
for k,v in pairs(negativeNumbers) do
verifyFloat2Nibbles((k/100) * -1, v)
end
ありがとう!あなたのコードは素晴らしいです。しかし、0.13の価値の意味は何ですか?値の整数部分を表す16進数の数はどこで制御しますか? – pascalc
'0.13'は' 0.12