ソケットプログラミングを使用して、UDPを介して別のハードウェアに送信するための数値の配列をパックしています。浮動小数点数のパックおよびアンパック時に、浮動小数点の不正確さを排除する方法を教えてください。
私がpack
の場合は12.2、次にunpack
の場合は12.199999892651となります。私が緯度と経度に関連する数字を扱っているので、私はそのような偏差を持つことはできません。
これは私が書いた簡単なスクリプトは次のとおりです。
use warnings;
use Time::HiRes qw (sleep);
@Data = (20.2, 30.23, 40.121, 1, 2, 3, 4, 6. 4, 3.2, 9.9, 0.1, 12.2, 0.99, 7.8, 999, 12.3);
$myArr = pack('f*', @Data);
print "$myArr\n\n";
@Dec = unpack('f*',$myArr);
print "@Dec";
出力は次のようになります。私は精度を制御することができます任意の方法は
20.2000007629395 30.2299995422363 40.1209983825684 1 2 3 4 6.40000009536743 3.20 000004768372 9.89999961853027 0.100000001490116 12.1999998092651 0.9900000095367 43 7.80000019073486 999 12.3000001907349
ありますか?
私はあなたが別のポストにあなたの2番目の質問を分割すべきだと思います。最初の質問と実際には関連していません。将来の訪問者がそのような方法で回答を見つけることは容易になります。 – ThisSuitIsBlackNot
12.2は122/10に等しい10進数です。しかし、 'm /(2 ** n)'という表現では表現できないため、Cの浮動小数点型に依存するデータ型を使って正確に表現することはできません。あなたのコードが12.2の瞬間に精度が失われます。内部的に浮動小数点値12.2はありません。我々はベース10で同様の問題を抱えていますが、彼らには慣れ親しんだので、私たちを驚かせることはありません。 1/3を10進数の形式で表す例があります。いくつかの対策では終了しますが、正確ではありません。 – DavidO
あなたの配列 '@ Data'は人工的です。通常は、浮動小数点数ではなくテキスト文字列で構成されます。値を浮動小数点としてパックするのではなく、テキスト "@Data"を送る必要があると思います。「他端」は、それが何であれ、文字列を空白で簡単に分割し、送信されたものを簡単に復元することができます。 – Borodin