本文介紹了當`Math.ulp`丟失時,如何計算`ulp`?的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!
問題描述
我需要給定雙精度值的ulp,但由于我是為代號1開發的,所以沒有提供ulp(double)。有沒有人知道用Java計算ulp的有效算法?Codename One僅提供了Math類中的一些方法(javadoc用于CN1版本),并且填補了MathUtil中的一些空白。
作為一種解決辦法,我使用此(不正確的)代碼,直到我找到一個可用的替代代碼:
private double ulp(double y) {
return y/1e15;
}
編輯:我為review發布了我自己的代碼。以防其他人需要這個。
推薦答案
好的,因為我沒有找到可用的替代品(ApacheHarmony和OpenJDK最終都使用了CN1上沒有的本機方法),所以我編寫了自己的版本(針對OpenJDK-Version進行了測試)。以防萬一有人需要。
至于代號一:我向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);
}
}
這篇關于當`Math.ulp`丟失時,如何計算`ulp`?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,






