Javascript.尽可能少地增加或减少浮动 [英] Javascript. Increase or decrease float as little as possible

查看:78
本文介绍了Javascript.尽可能少地增加或减少浮动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在javascipt中,我有如下这样的av浮点数:

In javascipt I have av floating point "a" like this:

var a = 5.;

现在,我想要一个新数字"b",它几乎比"a"大.我可以这样做:

Now I want a new number "b" that is barely larger than "a". I could do this:

var b = a + 1.e-10;

但是如果"a"是一个很小的数字怎么办?

But what if "a" is a really small number?

var a = 5.e-20;
var b = a + 1.e-10;

现在,"b"比"a"大许多数量级.
另外,如果我将"a"和"b"之间的差异过小,则较大的"a"可能会导致差异四舍五入.

Now "b" is many orders of magnitude larger than "a".
Also if I make the difference between "a" and "b" too small, a large "a" could cause the difference to be rounded off.

如何使数字"b"大于任何数字"a",但比大于"a"的任何其他数字更接近"a",或者如何使数字"b"大于小于"a",但比小于"a"的任何其他数字更接近"a".

How do I make the number "b" larger than any number "a", but closer to "a" than any other number that is larger than "a", or how do I make a number "b" that is smaller than "a" but closer to "a" than any other number smaller than "a".


太具体了:我正在寻找一个函数"makeLarger(a)",该函数需要一个数字"a"并返回一个数字"b",其中"b> a"将始终为true,而"c> a& & c< b对于任何数字" c始终为假.还有一个类似的函数"makeSmaller(a)".我希望"a"为任意数字,可以是正数,负数或零.


Too be more specific: I'm looking for a function "makeLarger(a)" That takes a number "a" and return a number "b" where "b>a" will always evaluate to true and "c>a && c<b" will always evaluate to false for any number "c". And also a similar function "makeSmaller(a)". I want "a" to be any number, positive, negative or zero.

推荐答案

假设a是正数,实数,并且与次标准态(在这种情况下,大于1.0020841800044864e-292)相距足够远,则以下内容应该起作用:

Assuming a is positive, real and sufficiently far away from being a subnormal (in this case, greater than 1.0020841800044864e-292), then the following should work:

var u = Number.EPSILON/2 + Number.EPSILON*Number.EPSILON;
var b = a + a*u;

请注意,b = a * (1+u) 不会起作用. (例如,如果a = 0.9999999999999998).

Note that b = a * (1+u) won't work. (e.g. if a = 0.9999999999999998).

基本思想是,浮点数之间的差距大致成比例,但只是逐步增加(对于同一 binade ).因此,面临的挑战是选择足够小的u,以使其在每个Binade的极端情况下都能发挥作用.

The basic idea is that the gap between floating point numbers is roughly proportional, but only increases in steps (it is the same for all numbers in the same binade). So the challenge is to choose u small enough so that it works for the extremes in each binade.

因此在不失一般性的前提下,考虑区间[1.0,2.0)中的数字a就足够了.我们需要确保

So without loss of generality, it is sufficient to consider the numbers a in the interval [1.0,2.0). We need to ensure that

Machine.EPSILON/2 < a*u < Machine.EPSILON*3/2

,以便最终的加法将沿正确的方向取整(而不是返回到a或2个增量).显而易见,上面定义的u满足这些属性.

so that the final addition will round in the correct direction (instead of back to a or 2 increments). It is fairly straightforward to show that the u defined above satisfies these properties.

可以向下走

var c = a - a*u;

P.S .:另一个选择虽然很难证明,但仍然是

P.S.: Another option, though trickier to prove, is

var v = 1 - Machine.EPSILON/2;
var b = a / v; # upwards
var c = a * v; # downwards

这具有在更大范围内工作的优势(任何正的,非超自然数).

This has the advantage of working for a greater range (any positive, non-subnormal real number).

对于次法线,您只需添加/减去Number.MIN_VALUE,因此将所有这些组合在一起即可得到:

For subnormals, you can just add/subtract Number.MIN_VALUE, so combining this all together you get:

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);
    }
 }

这篇关于Javascript.尽可能少地增加或减少浮动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆