java - 缺少 `ulp` 时如何计算 `Math.ulp`?

标签 java math double codenameone

我需要 ulp对于给定的 double 值,但由于我正在为代号 ONE 开发,因此未提供 ulp(double)。有谁知道用 Java 计算 ulp 的有效算法?代号 ONE 仅提供 Math 类(javadoc 为 CN1 版本)中的一些方法,一些空白由 MathUtil 填补.

作为解决方法,我使用此(不正确的)代码,直到找到有效的替代代码:

private double ulp(double y) {
    return y/1e15;
}

编辑:我“自己动手”并刚刚发布了我的 review 代码.以防万一其他人需要这个。

最佳答案

好的,因为我没有找到有效的替代品(Apache Harmony 和 OpenJDK 最终都使用了 CN1 上不可用的 native 方法),所以我编写了自己的版本(针对 OpenJDK 版本测试的结果)。以防万一有人需要它。

至于代号一:我提交了 MathUtil 类的补丁,希望它迟早会被添加。

/*
 * use a precalculated value for the ulp of Double.MAX_VALUE
 */
private static final double MAX_ULP = 1.9958403095347198E292;

/**
 * Returns the size of an ulp (units in the last place) of the argument.
 * @param d value whose ulp is to be returned
 * @return size of an ulp for the argument
 */
@Override
public double ulp(double d) {
    if (Double.isNaN(d)) {
        // If the argument is NaN, then the result is NaN.
        return Double.NaN;
    }

    if (Double.isInfinite(d)) {
        // If the argument is positive or negative infinity, then the
        // result is positive infinity.
        return Double.POSITIVE_INFINITY;
    }

    if (d == 0.0) {
        // If the argument is positive or negative zero, then the result is Double.MIN_VALUE.
        return Double.MIN_VALUE;
    }

    d = Math.abs(d);
    if (d == Double.MAX_VALUE) {
        // If the argument is Double.MAX_VALUE, then the result is equal to 2^971.
        return MAX_ULP;
    }

    return nextAfter(d, Double.MAX_VALUE) - d;
}

@Override
public double copySign(double x, double y) {
    return com.codename1.util.MathUtil.copysign(x,y);
}

private boolean isSameSign(double x, double y) {
    return copySign(x, y) == x;
}

/**
 * Returns the next representable floating point number after the first
 * argument in the direction of the second argument.
 *
 * @param start starting value
 * @param direction value indicating which of the neighboring representable
 *  floating point number to return
 * @return The floating-point number next to {@code start} in the
 * direction of {@direction}.
 */
@Override
public double nextAfter(final double start, final double direction) {
    if (Double.isNaN(start) || Double.isNaN(direction)) {
        // If either argument is a NaN, then NaN is returned.
        return Double.NaN;
    }

    if (start == direction) {
        // If both arguments compare as equal the second argument is returned.
        return direction;
    }

    final double absStart = Math.abs(start);
    final double absDir = Math.abs(direction);
    final boolean toZero = !isSameSign(start, direction) || absDir < absStart;

    if (toZero) {
        // we are reducing the magnitude, going toward zero.
        if (absStart == Double.MIN_VALUE) {
            return copySign(0.0, start);
        }
        if (Double.isInfinite(absStart)) {
            return copySign(Double.MAX_VALUE, start);
        }
        return copySign(Double.longBitsToDouble(Double.doubleToLongBits(absStart) - 1L), start);
    } else {
        // we are increasing the magnitude, toward +-Infinity
        if (start == 0.0) {
            return copySign(Double.MIN_VALUE, direction);
        }
        if (absStart == Double.MAX_VALUE) {
            return copySign(Double.POSITIVE_INFINITY, start);
        }
        return copySign(Double.longBitsToDouble(Double.doubleToLongBits(absStart) + 1L), start);
    }
}

关于java - 缺少 `ulp` 时如何计算 `Math.ulp`?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24104763/

相关文章:

jquery - 页面上的两个轮播不起作用

java - 行首 (^) 和行尾 ($) 的正则表达式边界匹配器不起作用

java - 用java编写一个基本的汽车租赁程序/问题

algorithm - 如何计算哈希算法中发生冲突的几率?

c++ - float 和 double 变量中的数字

c - 如果我使用 GPA 指针,为什么在使用 scanf ("%lf", GPA) 时会出现段错误,如果不是指针,则在使用 scanf ("%lf", &GPA) 时会出现段错误?

java - 使用 selenium webdriver 计算网格中的行数

java - 错误 :(31, 39) 错误:找不到符号变量上下文

math - Prolog 常见差异,多项式序列中的下一个数字

r - 如何计算R中给定分布的期望值?