我发现至少有两个数字,其中ActionScript的Number.toExponential(20)返回的结果不正确。
最明显的值是0。
trace(Number(0).toExponential(20)); // 0.00000000000000000000e-16
trace(Number(0).toExponential(2)); // 0.00e-16
trace(Number(0).toExponential(1)); // 0.0e-16
trace(Number(0).toExponential(0)); // 1e-15 - even worse!
我已经制作了一个Double类用于使用Numbers(IEEE 754双精度二进制浮点格式数字)。它需要一个数字并将所有位提取为符号,位和有效位数(后者打印包括隐式前导位),或者可以生成数字提供的符号,位和有效位数。有一些方法可以获得下一个和前一个最接近的可表示数字。 这是0在内部看起来像:
[Double number=0.00000000000000000000e-16 sign=1 exponent=-1023 isZero
significand=00000000000000000000000000000000000000000000000000000]
其他不正确的结果是最接近的可表示的数字大于Number.MAX_VALUE / 2和Number.MAX_VALUE / 4.
// Number.MAX_VALUE / 2.
trace(Number(8.98846567431157854072e+307).toExponential(20)); // 8.98846567431157854072e+307
// Nearest representable Number greater than Number.MAX_VALUE / 2. Printed incorrectly!
trace(Number(8.98846567431157953864e+307).toExponential(20)); // 0.e+327
// A Number two ULPs greater than Number.MAX_VALUE / 2.
trace(Number(8.98846567431158153448e+307).toExponential(20)); // 8.98846567431158153448e+307
// Nearest representable Number greater than Number.MAX_VALUE / 4. Printed incorrectly!
trace(Number(4.49423283715578976932e+307).toExponential(20)); // 0.e+327
以下是这四个数字在内部的样子:
[Double number=8.98846567431157854072e+307 sign=1 exponent=1022
significand=11111111111111111111111111111111111111111111111111111]
[Double number=0.e+327 sign=1 exponent=1023
significand=10000000000000000000000000000000000000000000000000000]
[Double number=8.98846567431158153448e+307 sign=1 exponent=1023
significand=10000000000000000000000000000000000000000000000000001]
[Double number=0.e+327 sign=1 exponent=1022
significand=10000000000000000000000000000000000000000000000000000]
到目前为止,所有三个错误打印的数字都有0个有效数字(隐含前导1),指数值1023(正常数字的Emax),1022(Emax - 1)或-1023(特殊指数值)对于±0和次正规数,Emin - 1)。
看起来toExponent至少没有正确处理这三种情况 。是否有其他数字打印不正确?
尝试检查toExponential是否会产生其他精度值的正确结果。
trace(Number(8.98846567431157953864e+307).toExponential(2)); // 0.e+309
trace(Number(8.98846567431157953864e+307).toExponential(1)); // 0.e+308
trace(Number(8.98846567431157953864e+307).toExponential(0)); // 1e+308 - less bad!
如果有人对我的Double课程感兴趣,我会发布它。我还编写了更快的实现next(x:Number)和previous(x:Number)函数,它们工作得非常快,而且不会弄乱数字的内部位。
参考文献: TeamCity REST API