向float中添加和减去精确值

Win*_*ter 6 java floating-point

题:

浮点的总量是有限的,大约有2 ^ 32个.使用浮动,您可以直接使用下一个或上一个java.lang.Math.nextAfter.我称之为一次飞跃.我的主要问题,由子问题组成,我如何使用跳跃导航浮动?

浮动导航

首先,如何将浮动一次移动到另一个浮动?

public static float moveFloat(float value, int leaps) {
    for(int i = 0; i < Math.abs(leaps); i++)
        value = Math.nextAfter(value, Float.POSITIVE_INFINITY * signum(leaps));
    return value;
}
Run Code Online (Sandbox Code Playgroud)

这种方式应该适用于理论,但实际上并未经过优化.我怎么能一次性添加呢?

我还需要知道2个花车之间有多少跳跃.以下是此示例的示例实现:

public static int getLeaps(float value, float destination) {
    int leaps = 0;
    float direction = signum(destination - value);

    while(value * direction < destination * direction) {
        value = Math.nextAfter(value, Float.POSITIVE_INFINITY * direction);
        leaps++;
    }

    return leaps;
}
Run Code Online (Sandbox Code Playgroud)

同样,这里的问题也一样.这种实现不合适.

额外:

我称之为飞跃,是否有实际名称?

背景:

我正在尝试用Java创建一个简单的2D物理引擎,我的浮点运算有问题.我了解了相对错误的浮动比较,它有点帮助,但它不是魔术.我想要的是与我的浮点完全一致.

我已经知道很多基数十个数字不能用浮点数精确表示但是在行政上,我并不在意.我想要的只是float基数2的精确算术.

为了简化,在我的碰撞检测和响应过程中,我检查形状是否重叠(让我们在这个例子中留在一个维度上),然后用它们的重量替换重叠的2个形状.

看这个例子: 一维碰撞检测和解决

如果黑线是float值(并且彼此之间的空间跳跃),无论精度如何,我想将两个形状(彩色线)完全放在棕色位置.(褐色位置由重量比和圆角决定.我称之为穿透是重叠区域/距离.如果穿透为5,则红色将被推动1,蓝色将被推动4).

问题是,我必须保持碰撞的渗透(在这种情况下,渗透正好是浮子的ULP,或1次跳跃)并且我怀疑这会导致不精确.如果穿透值大于形状的坐标,则它将不那么精确,因此它们不会在良好坐标处被完全替换.

我想象的是将碰撞的渗透保持为我需要从一个到另一个的跳跃量并随后使用它.

这是我当前代码的简化版本:

public class ReplaceResolver implements CollisionResolver {
    @Override
    public void resolve(Collision collision) {
        float deltaB = collision.weightRatio * collision.penetration; //bodyA's weight over the sum of the 2 (pre calculated)
        float deltaA = 1f - deltaB;

        //the normal indicates where the shape should be pushed. For now, my engine is only AA so a component of the normal (x or y) is always 0 while the other is 1
        if(deltaB > 0)
            replace(collision.bodyA, collision.normalB, deltaA); 

        if(deltaA > 0)
            replace(collision.bodyB, collision.normalA, deltaB);
    }

    private void replace(Body body, Vector2 normal, float delta) {
        body.getPosition().x += normal.x * delta; //body.getPosition() is a Vector2
        body.getPosition().y += normal.y * delta;
    }
}
Run Code Online (Sandbox Code Playgroud)

显然,这不能正常工作并累积浮点精度误差.我的碰撞检测可以很好地处理错误,它使用ULP检查浮点相等性.然而,由于ULP极低,它在越过0时会中断.

我可以简单地修复一个用于物理模拟的epsilon,但它会删除使用浮点数的全部要点.我想要使​​用的技术让用户隐式选择他的精度,理论上应该使用任何精度.

aka*_*ice 4

底层 IEEE 754 浮点模型具有以下属性:如果将位重新解释为整数,则在之后(或之前,取决于方向)获取下一个浮点就像获取下一个(或上一个)整数,即加或减1 将位模式重新解释为整数。

步进 n 次就是在位模式中添加(或减去)n。就这么简单,只要符号不改变,并且不会溢出到 NaN 或 Inf。

如果符号相同,两个浮点数之间不同浮点数的个数就是两个整数之差。

如果符号不同,由于浮点数具有类似于符号大小的表示形式,它不适合整数表示形式,因此您将不得不进行一些算术运算。