Java 计算一个数字需要添加到坐标中的次数,以更改地板值

Java 计算一个数字需要添加到坐标中的次数,以更改地板值,java,math,Java,Math,我有一个问题,它要求我计算一个数字必须添加到坐标x的次数,才能改变x的下限值。它必须支持正数和负数相加 下面的示例代码突出显示了问题 public static void main(String[] args) { double x = 10; double amountToAdd = -0.25; // must support positive + negative values int lastFlooredX = Integer.MIN_VALUE; in

我有一个问题,它要求我计算一个数字必须添加到坐标x的次数,才能改变x的下限值。它必须支持正数和负数相加

下面的示例代码突出显示了问题

public static void main(String[] args) {
    double x = 10;
    double amountToAdd = -0.25; // must support positive + negative values
    int lastFlooredX = Integer.MIN_VALUE;
    int i = 0;

    while (i++ < 100) {
        int flooredX = (int) Math.floor(x);
        if (lastFlooredX == flooredX) {
            throw new UnsupportedOperationException("Iterated over the same number twice!");
        }
        lastFlooredX = flooredX;

        int additionsBeforeFloorChanges = // I need help!;

        x += (amountToAdd * additionsBeforeFloorChanges);
    }
}
publicstaticvoidmain(字符串[]args){
双x=10;
double amountToAdd=-0.25;//必须支持正值+负值
int lastfooredx=整数.MIN\u值;
int i=0;
而(i++<100){
int floorredx=(int)数学地板(x);
如果(LastFloorRedX==FloorRedX){
抛出新的UnsupportedOperationException(“在同一个数字上迭代两次!”);
}
LastFloorRedX=FloorRedX;
int additionsBeforRefoorchanges=//我需要帮助!;
x+=(添加的数量*在重新设置前的添加量);
}
}
对于
amountToAdd
as-0.25输出和
x
as 10.1

1
4
对于
amountToAdd
作为0.25输出和
x
作为10.1输出

1
4

加法方法的问题是它很容易受到浮点舍入误差的影响

考虑一下+ve
x
d
的这种简单方法:

double xfloor = Math.floor(x);
int count = 0;
do
{
    x += d;
    count += 1;
    System.out.println(count + " " + x);
}
while(Math.floor(x) == xfloor);
System.out.format("Result: %d%n", count);
x=0
d=0.1
时,这将产生:

1 0.1
2 0.2
3 0.30000000000000004
4 0.4
5 0.5
6 0.6
7 0.7
8 0.7999999999999999
9 0.8999999999999999
10 0.9999999999999999
11 1.0999999999999999
Result: 11
这显然是不正确的

作为替代方案,我们可以使用除法来确定所需的步骤数。我们必须小心区分
x
d
具有相同或相反符号的情况

static int minAddFloorChange(double x, double d)
{
    if(d == 0) throw new IllegalArgumentException();

    double xa = Math.abs(x); 
    double da = Math.abs(d);

    if(x == 0 || (Math.signum(x) == Math.signum(d)))
    {           
        double xfrac = (xa == Math.rint(xa)) ? 1 : Math.ceil(xa) - xa;
        double count = xfrac / da;
        return (int)Math.ceil(count);
    }
    else
    {
        double xfrac = (x == Math.rint(xa)) ? 0 : xa - Math.floor(xa);
        double count = xfrac / da;
        return Math.max(1, (int)Math.ceil(count));
    }
}
注意,我并不是说这种方法完全不受舍入错误的影响——你需要一个比我更了解格式的人来解决这个问题

测试:

输出:

0.0 : 0.1 = 10
0.0 : -0.1 = 10
1.0 : 0.1 = 10
-1.0 : -0.1 = 10
1.0 : -0.1 = 1
-1.0 : 0.1 = 1
0.0 : 4.9E-324 = 2147483647
0.0 : -4.9E-324 = 2147483647
1.0 : 4.9E-324 = 2147483647
-1.0 : -4.9E-324 = 2147483647
1.0 : -4.9E-324 = 1
-1.0 : 4.9E-324 = 1

除了返回
1
(就我的测试而言)的整数外,这适用于所有情况。修复!!你能再次检查一下我是否遗漏了什么吗?在大多数情况下,这似乎是可行的,但是它会因某些输入而中断(x=74.82,d=-0.17在应该返回5时返回6)