Java 如果小数点以0.99结尾,我们怎么能把它四舍五入呢?

Java 如果小数点以0.99结尾,我们怎么能把它四舍五入呢?,java,algorithm,int,double,rounding,Java,Algorithm,Int,Double,Rounding,我正在做以下编程练习:。声明如下: 我们吃的只是水和干物质 约翰买了土豆:它们的重量是100公斤。土豆含有 水和干物质 水含量占总重量的99%。他认为他们 太湿了,把它们放在烤箱里,温度很低 失去一些水 在输出端,水含量仅为98% 以千克为单位的总重量是多少(含水量加干物质) 从烤箱里出来 他发现了50公斤,他认为自己犯了一个错误:“这么重 水含量变化这么小,我就输了!” 你能帮助他吗 用 int parameter p0 - initial percent of water- int para

我正在做以下编程练习:。声明如下:

我们吃的只是水和干物质

约翰买了土豆:它们的重量是100公斤。土豆含有 水和干物质

水含量占总重量的99%。他认为他们 太湿了,把它们放在烤箱里,温度很低 失去一些水

在输出端,水含量仅为98%

以千克为单位的总重量是多少(含水量加干物质) 从烤箱里出来

他发现了50公斤,他认为自己犯了一个错误:“这么重 水含量变化这么小,我就输了!”

你能帮助他吗

int parameter p0 - initial percent of water-
int parameter w0 - initial weight -
int parameter p1 - final percent of water -
土豆应返回烤箱的最终重量w1 截断为整数。例如:

土豆(9910098)-->50

我试图弄清楚我们如何手工计算最终重量。另外,我在以下线程中获得了帮助:

我编写了以下代码:

class Potatoes {

    public static long potatoes(int p0, int w0, int p1) {
        System.out.println("\ninitial percent of water p0: "+p0);
        System.out.println("initial weight w0: "+w0);
        System.out.println("final percent of water p1: "+p1);
        double left = (1 + (p1 / (100.0 - p1)));
        System.out.println("left: "+left);
        double right = (w0 * (1 - (p0/100.0)));
        System.out.println("right: "+right);
        System.out.println("double result: "+left * right);
        System.out.println("int result: "+(int)(left * right));
        return (int)(left * right);
    }
}
我观察到有些测试的输出与预期不同。困难在于该语句要求我们将最终权重截断为int。但如果我们这样做,则会出现一些边缘情况,
left*right
指令返回一个包含大量小数的数字,如:.999999;它期望下一个int(将其四舍五入)

最好用测试用例本身来解释:

import static org.junit.Assert.*;
import org.junit.Test;

public class PotatoesTest {

    private static void dotest(int p0, int w0, int p1, int expected) {
        assertEquals(expected, Potatoes.potatoes(p0, w0, p1));
    }

    @Test
    public void testResultDoesNotNeedRounding() {
        dotest(99, 100, 98, 50);
        dotest(82, 127, 80, 114);
        dotest(93, 129, 91, 100);
    }
    @Test
    public void testResultNeedsRoundingUp1(){
        dotest(92, 120, 88, 80);
    }
    @Test
    public void testResultNeedsRoundingUp2(){
        dotest(91, 132, 89, 108);
    }
}
当我们执行前面的测试时,控制台将提供以下输出:

initial percent of water p0: 99
initial weight w0: 100
final percent of water p1: 98
left: 50.0
right: 1.0000000000000009
double result: 50.00000000000004
int result: 50

initial percent of water p0: 82
initial weight w0: 127
final percent of water p1: 80
left: 5.0
right: 22.860000000000007
double result: 114.30000000000004
int result: 114

initial percent of water p0: 93
initial weight w0: 129
final percent of water p1: 91
left: 11.11111111111111
right: 9.029999999999994
double result: 100.33333333333326
int result: 100

initial percent of water p0: 92
initial weight w0: 120
final percent of water p1: 88
left: 8.333333333333332
right: 9.599999999999994
double result: 79.99999999999994
int result: 79
expected:<80> but was:<79>

initial percent of water p0: 91
initial weight w0: 132
final percent of water p1: 89
left: 9.090909090909092
right: 11.879999999999995
double result: 107.99999999999997
int result: 107
expected:<108> but was:<107>
此外,我还读到:

如果小数点以0.99结尾,我们怎么能把它四舍五入呢

编辑:我已经进行了测试,Math.round不能解决这种情况。这里我们还有两个测试用例:

import static org.junit.Assert.*;
import org.junit.Test;

public class PotatoesTest {

    private static void dotest(int p0, int w0, int p1, int expected) {
        assertEquals(expected, Potatoes.potatoes(p0, w0, p1));
    }

    @Test
    public void mathRoundDoesNotWork1(){
      dotest(89,53,85,38);
    }
    @Test
    public void mathRoundDoesNotWork2(){
      dotest(82,134,77,104);
    }
}
作为代码:

class Potatoes {

    public static long potatoes(int p0, int w0, int p1) {
        System.out.println("\ninitial percent of water p0: "+p0);
        System.out.println("initial weight w0: "+w0);
        System.out.println("final percent of water p1: "+p1);
        double left = (1 + (p1 / (100.0 - p1)));
        System.out.println("left: "+left);
        double right = (w0 * (1 - (p0/100.0)));
        System.out.println("right: "+right);
        System.out.println("double result: "+left * right);
        System.out.println("int result: "+(int)(left * right));
        return Math.round(left*right);
    }
}
我们在输出中看到:

initial percent of water p0: 89
initial weight w0: 53
final percent of water p1: 85
left: 6.666666666666667
right: 5.829999999999999
double result: 38.86666666666666
int result: 38
expected:<38> but was:<39>

initial percent of water p0: 82
initial weight w0: 134
final percent of water p1: 77
left: 4.3478260869565215
right: 24.120000000000008
double result: 104.86956521739134
int result: 104
expected:<104> but was:<105>
初始含水率p0:89
初始重量w0:53
水的最终百分比p1:85
左:6.66667
右:5.82999999999
双重结果:38.866666
int结果:38
预期:但是:
初始含水率p0:82
初始重量w0:134
水的最终百分比p1:77
左:4.3478260869565215
右:24120000000000008
双重结果:104.86956521739134
int结果:104
预期:但是:
问题是:只有当一个双精度结果包含一个非常接近下一个整数的数字,这意味着它的格式是:100.999999时,我们如何取整。。。(数字{9 n小数})

阅读启示:计算机不是魔法;一个
double
只能代表2^64个不同的数字,这意味着:并不是每个数字都在其中(0和1之间有无穷多个数字,更不用说负无穷大和正无穷大之间了;显然,“无限大”比2^64多得多!)。计算机以二进制计数,人类以十进制计数,而这两者并不相同

从那一批2^64的数字(双倍数字可以表示)到人类形体,它可能看起来很丑

解决方案是认识到你不能把双倍打印给人类,并让它们合理。相反,在渲染它们时需要一种策略,例如,通过包含要渲染的精度。因此:

System.out.printf("%.2f\n", someDouble); // this is how you print doubles.
System.out.println(someDouble); // this is never a good idea.
String x = String.format("%.2f", someDouble); // If you need it as a string.
文本
%.2f
是String.format-ese,表示“打印双精度”;分隔符“”后不超过2位


编辑:修复了代码片段第一行中“println”到“printf”的问题。

我不明白为什么不回答这个问题。。。?你想把小数点四舍五入到零就行了。。。有些答案显示为使用(返回一个
)。您说您已经阅读了这些链接-它们没有回答您的问题吗?如果没有,原因是什么?数学圆应该做你需要做的事试过数学圆(数字)?我已经把这个问题作为一个重复题结束了。如果你的问题真的不同,我们可以重新开始,但我看不到。
System.out.printf("%.2f\n", someDouble); // this is how you print doubles.
System.out.println(someDouble); // this is never a good idea.
String x = String.format("%.2f", someDouble); // If you need it as a string.