有没有一个合理的快速方法来提取指数和尾数从一个数字在JavaScript?
在JavaScript中,没有办法得到数字后面的位,这让我觉得我在看一个因式分解问题:找到m
和n
,使得对于给定的k
,2^n * m = k
。由于整数因式分解是NP,我只能假设这是一个相当困难的问题。
我正在实现一个用于生成JavaScript的GHC插件,并且需要实现decodeFloat_Int#
和decodeDouble_2Int#
primitive operations;我想我可以重写基础库的部分,这些部分使用操作来做其他方式(这应该不会太难,因为所有数字类型都有Number作为它们的表示),但如果我不必这样做就好了。
有没有什么方法可以通过一些黑暗JavaScript巫术,聪明的数学或其他方法,以一种甚至远程性能的方式来做到这一点,或者我应该只是全力以赴,在基础库?
编辑基于ruakh和Louis Wasserman的优秀答案,我提出了以下实现,它似乎工作得很好:
function getNumberParts(x) {
if(isNaN(x)) {
return {mantissa: -6755399441055744, exponent: 972};
}
var sig = x > 0 ? 1 : -1;
if(!isFinite(x)) {
return {mantissa: sig * 4503599627370496, exponent: 972};
}
x = Math.abs(x);
var exp = Math.floor(Math.log(x)*Math.LOG2E)-52;
var man = x/Math.pow(2, exp);
return {mantissa: sig*man, exponent: exp};
}
字符串
8条答案
按热度按时间r6l8ljro1#
使用新的
ArrayBuffer
访问数组,实际上可以通过从Uint8Array
中提取尾数和指数来检索确切的尾数和指数。如果您需要更快的速度,请考虑重用Float64Array
。字符串
我还创建了一些测试用例。
0
失败,因为2^-1023有另一种表示。型
prdp8dxp2#
ECMAScript没有定义任何直接的方法来实现这一点;但无论如何,这不是一个与素因子分解相同意义上的“因子分解问题”。
理论上,你可以很快地完成你想要的,首先处理符号,然后使用二叉树方法(或对数)来找到指数,最后除以2的相关幂来得到尾数;但不幸的是,在实践中实现这一点可能有点棘手(对于特殊情况,如非正规化的数字)。我建议你阅读6.1.6.1:ECMAScript规范的数字类型一节,了解你必须处理什么情况。
d5vmydt93#
整数因式分解对于这一点来说几乎是不必要的。
这个指数基本上就是以2为底的对数的底数,这并不难计算。
下列程式码会通过QuickCheck测试,以及无穷大和负无穷大的测试:
字符串
我使用
quickCheck (\ d -> decodeFloat d == decode d)
测试了它,并分别在正无穷大和负无穷大上显式测试了它。这里使用的唯一基本操作是左移、双乘、双除、无穷大和NaN测试,据我所知JavaScript支持这些操作。
irlmq6kh4#
对于基数为10的数组,你可以用
字符串
如果你不在乎结果部分是文本而不是数字,或者指数部分的前面可能有一个加号,那么你可以跳过
parseFloat
和parseInt
步骤,直接从数组的[0]和[1]处获取部分。vzgqcmou5#
虽然我喜欢这个公认的解决方案,但使用它来处理任意碱基会重新引入
Math.log
和Math.pow
引起的所有错误。字符串
NaN和Infinite的情况可以很容易地添加。如果
+0
和-0
之间的区别很重要:型
bq9c1y666#
下面我们来看看如何得到指数:
字符串
1000将导致exp = 3
z9zf31ra7#
我的Haskell是不存在的。这里有一个JavaScript的解决方案。正如其他人所指出的,关键是计算二进制对数以获得指数。
从http://blog.coolmuse.com/2012/06/21/getting-the-exponent-and-mantissa-from-a-javascript-number/
字符串
f1tvaqid8#
如果你只需要尾数长度,
字符串