【发布时间】:2016-09-01 19:21:44
【问题描述】:
我正在打包一组数字,以便使用套接字编程通过 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
有什么方法可以控制精度吗?
【问题讨论】:
-
我认为您应该将第二个问题拆分为单独的帖子;它与第一个问题并没有真正的关系。这样以后的访问者会更容易找到答案。
-
12.2 是一个十进制数,等于 122/10。但是它不能用表达式
m/(2**n)来表示,因此不能用依赖于C的浮点类型的数据类型来准确表示。当您的代码遇到数字 12.2 时,精度就会丢失——在内部没有浮点值 12.2 这样的东西。我们在 base-10 中也有类似的问题,但已经习惯了它们,所以它们并不让我们感到惊讶。例如,以十进制形式表示 1/3:0.33?在某些方面接近,但不准确。 -
您的数组
@Data是人造的。通常它将由文本字符串组成,而不是浮点数。我认为您需要发送文本"@Data"而不是尝试将值打包为浮点数。 “另一端”,无论它是什么,都可以轻松地将字符串拆分为空格并准确恢复发送的内容。 -
拜托,总是
use strict,即使在最琐碎的 Perl 程序中 -
假设您在地球上以度为单位处理纬度和经度,那么赤道处 12.2 和 12.199999892651 之间的误差为 12mm。