Mar*_*eim 2 javascript floating-point precision rounding-error
在javascipt中,我有如下这样的av浮点数:
var a = 5.;
Run Code Online (Sandbox Code Playgroud)
现在,我想要一个新数字“ b”,它几乎比“ a”大。我可以这样做:
var b = a + 1.e-10;
Run Code Online (Sandbox Code Playgroud)
但是,如果“ a”是一个很小的数字怎么办?
var a = 5.e-20;
var b = a + 1.e-10;
Run Code Online (Sandbox Code Playgroud)
现在“ b”比“ a”大许多数量级。
另外,如果我使“ a”和“ b”之间的差异过小,则较大的“ a”可能会导致差异四舍五入。
如何使数字“ b”大于任何数字“ a”,但比大于“ a”的任何其他数字更接近“ a”,或者如何使数字“ b”小于“ a”,但比小于“ a”的任何其他数字更接近“ a”。
编辑:
太具体了:我正在寻找一个函数“ makeLarger(a)”,该函数需要一个数字“ a”并返回一个数字“ b”,其中“ b> a”将始终为true,而“ c> a” && c <b“对于任何数字” c“始终为false。还有一个类似的函数“ makeSmaller(a)”。我希望“ a”为任意数字,可以是正数,负数或零。
假设它a是正数,实数,并且与次正规量(在这种情况下,大于1.0020841800044864e-292)相距足够远,那么以下方法应该起作用:
var u = Number.EPSILON/2 + Number.EPSILON*Number.EPSILON;
var b = a + a*u;
Run Code Online (Sandbox Code Playgroud)
请注意,这b = a * (1+u) 将不起作用。(例如,如果a = 0.9999999999999998)。
基本思想是,浮点数之间的差距大致成比例,但只是逐步增加(对于同一binade中的所有数字而言,差距都是相同的)。因此,面临的挑战是选择u足够小的尺寸,使其适用于每个binade中的极端情况。
因此,在不失一般性的前提下,考虑a区间[1.0,2.0)中的数字就足够了。我们需要确保
Machine.EPSILON/2 < a*u < Machine.EPSILON*3/2
Run Code Online (Sandbox Code Playgroud)
这样最终的加法将沿正确的方向舍入(而不是返回a2或1的增量)。可以很直接地证明上述u定义满足这些属性。
要向下走,你可以做
var c = a - a*u;
Run Code Online (Sandbox Code Playgroud)
PS:尽管很难证明,但另一个选择是
var v = 1 - Machine.EPSILON/2;
var b = a / v; # upwards
var c = a * v; # downwards
Run Code Online (Sandbox Code Playgroud)
这具有在更大范围内工作的优势(任何正的,非超自然数)。
对于次法线,您可以添加/减去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);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
170 次 |
| 最近记录: |