as3数字类型 - 大数字的逻辑问题

时间:2011-09-27 11:36:08

标签: actionscript-3

我很好奇我们的团队中发现了一个非常大的问题:

var n:Number = 64336512942563914;
trace(n < Number.MAX_VALUE); // true
trace(n); // 64336512942563910

var a1:Number = n +4;
var a2:Number = a1 - n;
trace(a2); // 8  Expect to see 4
trace(n + 4 - n); // 8

var a3:Number = parseInt("64336512942563914");
trace(a3); // 64336512942563920

n++;
trace(n); //64336512942563910
trace(64336512942563914 == 64336512942563910); // true

这里发生了什么?

虽然n很大,但它比Number.MAX_VALUE小,所以为什么我会看到这种奇怪的行为?

我认为这可能是trace'出来时格式化大数字的问题,但这并不能解释n + 4 - n == 8

这是一个奇怪的浮点数问题吗?

5 个答案:

答案 0 :(得分:3)

是的,这是一个浮点问题,但它不是一个奇怪的问题。这是所有预期的行为。

AS3中的数字数据类型实际上是“IEEE二进制浮点运算标准(IEEE-754)”(source)指定的“64位双精度格式”。因为您分配给 n 的数字太多而无法容纳64位,所以它会四舍五入,这就是所有“奇怪”结果的原因。

如果你需要做一些精确的大整数运算,你将不得不使用一个自定义的大整数类,例如this one

答案 1 :(得分:1)

flash中的数字是双精度浮点数。这意味着它们存储了许多有效数字和指数。由于存储器限制,它有利于数字精度的更大范围的可表达数字。在某些时候,会出现具有大量有效数字的数字。这是你所看到的;最低有效数字正在四舍五入。谷歌双精度浮点数,你会发现一堆技术信息为什么。

这是数据类型的本质。如果你需要精确的数字,你应该坚持使用uint或int整数。其他语言有固定点或bigint数字处理库(有时称为BigInt或Decimal),这些库是int和long的包装器,以代表内存消耗来表示更大的数字。

答案 2 :(得分:1)

我们有一个从Java复制的BigDecimal as3实现,我们用它来进行所有计算。在交易应用程序中,浮点错误是不可接受的。

答案 3 :(得分:1)

为了在使用Numbers时使用整数数学安全,我检查了AS3 documentation的数字,并说明:

  

Number类可用于表示远远超出的整数值   int和uint数据类型的有效范围。数字数据类型   与32相比,最多可以使用53位来表示整数值   int和uint可用的位。

一个53位整数可以让你达到2 ^ 53 - 1,如果我没错,那就是9007199254740991,或大约9千万亿。在指数中使用有助于构成64位数的其他11位。问题中使用的数字约为64.3千万亿。超过该点(9千万亿)需要比分配的有效数字部分(尾数)更多的比特,因此发生舍入。一个有用的video解释了为什么这是有意义的(由PBS Studio的无限系列)。

所以是的,必须搜索BigInt等外部资源。希望我链接的资源对某人有用。

答案 4 :(得分:0)

这确实是一个浮点数近似问题。

我猜n与4相比较大,因此它必须坚持与其年龄的孩子: trace(n - n + 4)没问题,因为它确实n-n = 0; 0 + 4 = 4;

实际上,Number不是用于大整数的类型,而是浮点数。如果要计算大整数,则必须保持在uint.MAX_VALUE的限制内。

干杯!