如果小数以0.99结尾,我们如何舍入小数? [重复]

问题描述 投票:-1回答:1
我正在执行以下编程练习:Drying Potatoes。该语句是:

我们只吃水和干物质。

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

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

在输出时,水含量仅为98%。

[千克总重量是多少(水分加干物质)从烤箱出来吗?

他发现50公斤,他认为自己犯了一个错误:“这么重因水分含量的微小变化而迷失了!“

你能帮他吗?

写功能土豆和>

int parameter p0 - initial percent of water- int parameter w0 - initial weight - int parameter p1 - final percent of water -

土豆应该返回从烤箱w1出来的最终重量截断为int。示例:

potatoes(99,100,98)-> 50

我试图找出如何手工计算最终重量。另外,我在以下线程中获得了帮助:How could we calculate the final weight, knowing the initial and final water percentage, and initial weight‽??

我编写了以下代码:

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指令将返回一个带有很多小数的数字,例如:.9999999;。并且它期望下一个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>

因此,如您所见,前三个测试通过了,因为它们不需要四舍五入并且可以被截断为int。但是最后两个失败了,因为该练习希望他们将其四舍五入。

此外,我还编写了以下内容以便能够通过测试用例,但是我知道应该有更好的方法:

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 String.valueOf(left * right).contains(".99") ? (int)(Math.ceil(left * right)) : (int)(left * right); } }

此外,我读过:

编辑:我已经测试过,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>

问题是:只有在双精度结果包含与下一个整数非常接近的数字(即其格式为:100.999999 ...(数字。{9 n个小数})时,才如何舍入?

我正在执行以下编程练习:烘干土豆。声明是:我们所吃的只是水和干物质。约翰买了土豆:它们的重量为100公斤。土豆包含...

java algorithm int double rounding
1个回答
1
投票
阅读this以获得启发:计算机不是神奇的;计算机不是神奇的。 double只能表示2 ^ 64个不同的数字,这意味着:并非每个数字都在其中(0和1之间有无穷大的数字,更不用说在负无穷大和正无穷大之间了;显然,“无穷大无穷大”是远远超过2 ^ 64!)。计算机以二进制数计数,人类以十进制数计数,并且这两者是不相同的。
© www.soinside.com 2019 - 2024. All rights reserved.