我正在尝试更详细地了解Java中的浮点运算。如果我正确阅读文档,则对于任何给定的双x,以下内容成立:
x - Math.ulp(x) == Math.nextAfter(x, Double.NEGATIVE_INFINITY);
x + Math.ulp(x) == Math.nextAfter(x, Double.POSITIVE_INFINITY);
问题:这种情况总是如此,或者是否有一些特殊情况会导致结果不同?
答案 0 :(得分:10)
这个程序:
#cssmenu,
#cssmenu ul,
#cssmenu ul li,
#cssmenu ul li a {
margin: 0;
padding: 0;
border: 0;
list-style: none;
line-height: 1;
display: block;
position: relative;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
#cssmenu:after,
#cssmenu > ul:after {
content: ".";
display: block;
clear: both;
visibility: hidden;
line-height: 0;
height: 0;
}
#cssmenu {
width: 100%;
border-bottom: 3px solid #a24fef;
font-family: Raleway, sans-serif;
line-height: 1;
}
#cssmenu ul {
background: rgb(220, 220, 0);
background: rgba(220, 220, 0, 0);
}
#cssmenu > ul > li {
float: left;
}
#cssmenu.align-center > ul {
font-size: 0;
text-align: center;
}
#cssmenu.align-center > ul > li {
display: inline-block;
float: none;
}
#cssmenu.align-right > ul > li {
float: right;
}
#cssmenu.align-right > ul > li > a {
margin-right: 0;
margin-left: -4px;
}
#cssmenu > ul > li > a {
z-index: 2;
padding: 18px 25px 12px 25px;
font-size: 25px;
font-weight: 400;
text-decoration: none;
color: #444444;
-webkit-transition: all 1s ease;
-moz-transition: all 1s ease;
-ms-transition: all 1s ease;
-o-transition: all 1s ease;
transition: all 1s ease;
margin-right: -4px;
}
#cssmenu > ul > li.active > a,
#cssmenu > ul > li:hover > a,
#cssmenu > ul > li > a:hover {
color: #ffffff;
}
#cssmenu > ul > li > a:after {
position: absolute;
left: 0;
bottom: 0;
right: 0;
z-index: -1;
width: 100%;
height: 120%;
border-top-left-radius: 8px;
border-top-right-radius: 8px;
content: "";
-webkit-transition: all 1s ease;
-o-transition: all 1s ease;
transition: all 1s ease;
-webkit-transform: perspective(5px) rotateX(2deg);
-webkit-transform-origin: bottom;
-moz-transform: perspective(5px) rotateX(2deg);
-moz-transform-origin: bottom;
transform: perspective(5px) rotateX(2deg);
transform-origin: bottom;
}
#cssmenu > ul > li.active > a:after,
#cssmenu > ul > li:hover > a:after,
#cssmenu > ul > li > a:hover:after {
background: #a24fef;
}
输出:
public class Test {
public static void main(String[] args) {
double x = 1;
System.out.println(x - Math.ulp(x) == Math.nextAfter(x, Double.NEGATIVE_INFINITY));
System.out.println(x + Math.ulp(x) == Math.nextAfter(x, Double.POSITIVE_INFINITY));
}
}
连续双精度之间的差异在每个正常整数幂为2时发生变化,包括1.0。其中一项测试必须失败,因为它假设不断有差异。 Math.ulp(double)被定义为返回“此浮点值与接下来更大的双值之间的正距离”,因此当距离不同时,减法命题为假。
答案 1 :(得分:4)
我想要检查的直接情况是0,+无穷大和-infinity和NaN:
static void check(double x) {
double a, b;
System.out.printf(
"%9s %9s %23s %5s%n",
x, a = x - Math.ulp(x), b = Math.nextAfter(x, Double.NEGATIVE_INFINITY), a == b);
System.out.printf(
"%9s %9s %23s %5s%n",
x, a = x + Math.ulp(x), b = Math.nextAfter(x, Double.POSITIVE_INFINITY), a == b);
System.out.println();
}
public static void main(String[] args) throws java.lang.Exception {
check(0);
check(Double.POSITIVE_INFINITY);
check(Double.NEGATIVE_INFINITY);
check(Double.NaN);
}
输出:
0.0 -4.9E-324 -4.9E-324 true
0.0 4.9E-324 4.9E-324 true
Infinity NaN 1.7976931348623157E308 false
Infinity Infinity Infinity true
-Infinity -Infinity -Infinity true
-Infinity NaN -1.7976931348623157E308 false
NaN NaN NaN false
NaN NaN NaN false
表达式在NaN
情况下不相等并不令人惊讶(根据NaN的定义);但这些表达式对于+ infinity和-infinity也不是真的(见最后一栏)。
这个答案并不是为了提供有问题的值的详尽列表,而是为了表明存在一些有问题的值。