我有以下代码......
public class Point {
private double x;
private double y;
static private final double RADTODEG = 180.0d / Math.PI ;
static private final double DEGTORAD = Math.PI / 180.0d;
/**
* Rotates the point by a specific number of radians about a specific origin point.
* @param origin The origin point about which to rotate the point
* @param degrees The number of radians to rotate the point
*/
public void rotateByRadians(Point origin, double radians) {
double cosVal = Math.cos(radians);
double sinVal = Math.sin(radians);
double ox = x - origin.x;
double oy = y - origin.y;
x = origin.x + ox * cosVal - oy * sinVal;
y = origin.y + ox * sinVal + oy * cosVal;
}
/**
* Rotates the point by a specific number of degrees about a specific origin point.
* @param origin The origin point about which to rotate the point
* @param degrees The number of degrees to rotate the point
*/
public void rotateByDegrees(Point origin, double degrees) {
rotateByRadians(origin, degrees * DEGTORAD);
}
/**
* Rotates the point by the specified number of radians about the axis' origin (0,0). To rotate about a specific origin point, see rotateByRadians(Point, double)
* @param radians Measure of radians to rotate the point
*/
public void rotateByRadians(double radians) {
if(isEmpty()) // Since we're rotating about 0,0, if the point is 0,0, don't do anything
return;
double cosVal = Math.cos(radians);
double sinVal = Math.sin(radians);
double newx = x * cosVal - y * sinVal;
double newy = x * sinVal + y * cosVal;
x = newx;
y = newy;
}
/**
* Rotates the point by the specified number of degrees about to the axis' origin (0,0). To rotate about a specific origin point, see rotateByDegrees(Point, double)
* @param degrees Measure of degrees to rotate the point
*/
public void rotateByDegrees(double degrees) {
rotateByRadians(degrees * DEGTORAD);
}
当给出一个点,比如0,200时,问题就出现了。将旋转(约为轴原点0,0)调用180度应该是(0,-200)。 x
坐标不应该更改。然而,它最终是(-2.4492935982947064E-14,-200)。我尝试使用strictfp
但它并没有什么区别。如果旋转的坐标为零,则仅影响结果。非零值工作正常。任何想法为什么这不准确?
代码如下:
Point p = new Point(0.0d, 200.0d);
p.rotateByDegrees(180.0d);
System.out.println(p);
提供输出:
shapelib.Point Object {x: -2.4492935982947064E-14 y: -200.0}
答案 0 :(得分:3)
无论好坏,这就是浮点数学的方式。来自http://mindprod.com/jgloss/floatingpoint.html:
“将float和double视为代表物理测量值 如果他们的橱柜制造商制作了一张桌子,那么他们会抱怨的是6.000000000001 一英尺长。类似地,不要抱怨不可避免的微小 浮点运算结果中的错误,例如数学。 COS( Math.toRadians(90))没有出现在零上。 ( 如果你想 完美,使用int,long,BigInteger或BigDecimal。 )“
答案 1 :(得分:1)
浮点运算不完全准确。在大多数情况下,10 ^ -14功率的误差就足够了。
如果您计算Math.sin(Math.PI)
,您将获得1.2246467991473532E-16
。为什么你需要在你的情况下准确地得到0?
答案 2 :(得分:1)
到目前为止提供的答案都是正确的,但它们缺少一个基本点。
浮点数可以采用的可能值范围不是连续的。相反,它有漏洞。所以你可以想象从0.1到0.2,而不是有无限数量的数字,只有一个有限的数字。
这就是浮点运算不准确的大部分原因。计算机无法准确代表您想要的每个实数。相反,他们只能从实际价值中获得一些小的epsilon。
例如,你不能准确地表示分数2/10。如果你打印出这个数字的所有小数位,你会发现它像0.20000000000000001。
请参阅此处以获取更全面的说明:http://floating-point-gui.de/