Java 取而代之的是RoundingMode.DOWN,表示向上取整

Java 取而代之的是RoundingMode.DOWN,表示向上取整,java,rounding,bigdecimal,Java,Rounding,Bigdecimal,我正试图编写一个程序,用用户提供的牛顿法,以指定的精度(k)计算整数(n)的平方根。该计划运行良好,但我注意到我认为是一个舍入问题。有人能帮我解决这个问题吗 例如: 输入:n=81和k=7/输入:n=87026和k=11 程序正在打印:9.0000001/程序正在打印:295.00169491039 我要打印的内容:9.0000000/我要打印的内容:295.00169491038 这是我的密码: Scanner userInput = new Scanner(System.in); //p

我正试图编写一个程序,用用户提供的牛顿法,以指定的精度(k)计算整数(n)的平方根。该计划运行良好,但我注意到我认为是一个舍入问题。有人能帮我解决这个问题吗

例如:

  • 输入:n=81和k=7/输入:n=87026和k=11
  • 程序正在打印:9.0000001/程序正在打印:295.00169491039
  • 我要打印的内容:9.0000000/我要打印的内容:295.00169491038
这是我的密码:

Scanner userInput = new Scanner(System.in);
//print instructions and scan user input
System.out.println("~ This program computes the square root of an integer ~");
System.out.print("\n" + "Enter a non-negative integer [not greater than 1 billion (10^9)] n: ");
int n = userInput.nextInt();
System.out.print("\n" + "Enter a non-negative integer [not greater than 10 thousand (10^4)] k: ");
int k = userInput.nextInt();
userInput.close();
// declaring and converting variables
int p = (k + 1);
BigDecimal num = new BigDecimal(n);
BigDecimal guess = new BigDecimal(n);
BigDecimal newGuess;
BigDecimal sqrt;
// calculating error using int p
BigDecimal error = BigDecimal.ONE.movePointRight(-p);
// calculating guess using int p
BigDecimal diff = BigDecimal.ONE.scaleByPowerOfTen(p);
// newton's loop 
while (diff.compareTo(error) == 1) {
    newGuess = guess.subtract(
        ((guess.multiply(guess)).subtract(num))
        .divide(guess.add(guess), k, RoundingMode.DOWN));
    diff = newGuess.subtract(guess);
    if (diff.signum() == -1) {
        diff = diff.abs();
    }
    guess = newGuess;
}
// printing sqrt to screen    
sqrt = guess;
System.out.println("loop calculated: " + "\n" + sqrt);

在循环中,根据牛顿法迭代计算一个和,其中每个和被舍入并导致误差。为了说明这一点,另外输出
guess
的初始值和
diff
的所有值非常有用。对于示例
n=81,k=7
,输出为:

guess: 81
diff: 40.0000000
diff: 19.5121951
diff: 8.8591124
diff: 3.1073634
diff: 0.5070567
diff: 0.0142611
diff: 0.0000112
diff: 0E-7
loop calculated: 
9.0000001
如果从
guess
中减去所有
diff
-值,则准确值为
9.0000001
,即单个舍入误差导致偏差
0.0000001
。要更改此行为,可在循环之前将刻度增加一,例如,
k+=1
,并使用
guess=guess.setScale(k-1,RoundingMode.DOWN)重置为实际值在循环之后。那么输出是:

guess: 81
diff: 40.00000000
diff: 19.51219512
diff: 8.85911242
diff: 3.10736339
diff: 0.50705669
diff: 0.01426108
diff: 0.00001129
diff: 0E-8
loop calculated: 
9.0000000
现在,结果与预期相符。可以使用第二个示例
n=87026,k=11
验证更改,对于该示例,输出没有更改:

guess: 87026
diff: 43512.50000000000
diff: 21755.75001149068
diff: 10876.87510915519
diff: 5436.43840462864
diff: 2714.22604199009
diff: 1349.16761702433
diff: 659.01405739182
diff: 300.74946658011
diff: 107.35187252479
diff: 18.35523727653
diff: 0.56993647588
diff: 0.00055055104
diff: 5.1E-10
diff: 0E-11
loop calculated: 
295.00169491039
结果中有一个模拟错误。修改后的输出为:

guess: 87026
diff: 43512.500000000000
diff: 21755.750011490686
diff: 10876.875109155187
diff: 5436.438404628644
diff: 2714.226041990089
diff: 1349.167617024336
diff: 659.014057391816
diff: 300.749466580112
diff: 107.351872524786
diff: 18.355237276533
diff: 0.569936475871
diff: 0.000550551041
diff: 5.13E-10
diff: 0E-12
loop calculated: 
295.00169491038 
按照预期值