在javascipt中我有像这样的浮动点“a”:
var a = 5.;
现在我想要一个比“a”略大的新数字“b”。我能做到这一点:
var b = a + 1.e-10;
但是,如果“a”是一个非常小的数字呢?
var a = 5.e-20;
var b = a + 1.e-10;
现在“b”比“a”大许多个数量级 此外,如果我将“a”和“b”之间的差异设置得太小,那么大的“a”可能会导致差异四舍五入。
如何使数字“b”大于任何数字“a”,但比任何大于“a”的数字更接近“a”,或者如何使数字“b”更大小于“a”但比“a”更接近“a”。
编辑:
更具体:我正在寻找一个函数“makeLarger(a)”,它取一个数字“a”并返回一个数字“b”,其中“b> a”总是评估为真,“c> a&对于任何数字“c”,& c< b“将始终评估为false。还有一个类似的功能“makeSmaller(a)”。我希望“a”为任意数字,正数,负数或零。
答案 0 :(得分:4)
假设a
是正面的,真实的并且远离低于正常(在这种情况下,大于1.0020841800044864e-292
),则以下内容应该有效:
var u = Number.EPSILON/2 + Number.EPSILON*Number.EPSILON;
var b = a + a*u;
请注意,b = a * (1+u)
不会工作。 (例如,如果a = 0.9999999999999998
)。
基本思想是浮点数之间的差距大致成比例,但只是逐步增加(对于同一binade中的所有数字都是相同的)。所以挑战在于选择u
足够小,以便它适用于每个binade的极端。
因此,在不失一般性的情况下,考虑区间[1.0,2.0]中的数字a
就足够了。我们需要确保
Machine.EPSILON/2 < a*u < Machine.EPSILON*3/2
以便最终添加将以正确的方向进行舍入(而不是返回a
或2个增量)。显示上面定义的u
满足这些属性非常简单。
向下走,你可以做到
var c = a - a*u;
P.S。:另一种选择,虽然难以证明,但是
var v = 1 - Machine.EPSILON/2;
var b = a / v; # upwards
var c = a * v; # downwards
这具有工作更大范围(任何正,非次正规实数)的优势。
对于次正规,您只需添加/减去Number.MIN_VALUE
,因此将这些组合在一起得到:
function nextup(a) {
var v = 1 - Number.EPSILON/2;
if (a >= Number.MIN_VALUE / Number.EPSILON) {
// positive normal
return (a/v);
} else if (a > -Number.MIN_VALUE / Number.EPSILON) {
// subnormal or zero
return (a+Number.MIN_VALUE);
} else {
// negative normal or NaN
return (a*v);
}
}
function nextdown(a) {
var v = 1 - Number.EPSILON/2;
if (a >= Number.MIN_VALUE / Number.EPSILON) {
// positive normal
return (a*v);
} else if (a > -Number.MIN_VALUE / Number.EPSILON) {
// subnormal or zero
return (a-Number.MIN_VALUE);
} else {
// negative normal or NaN
return (a/v);
}
}
答案 1 :(得分:0)
您可以使用Big Number方法 - 将您的号码存储为其数字序列:
即G。 123... many digits here ...45
为[1, 2, 3, .., 4, 5]
所以你可以处理你的浮动数据,并且你的花车的精确度非常高。
有几个js模块,例如http://jsfromhell.com/classes/bignumber
答案 2 :(得分:0)
这可能是非正统的,但您可以执行以下操作:
有一些微调方面可以解决,但这将完成它。
我不想为这个例子编写代码,但这很简单。