我们只吃水和干物质。约翰买了土豆:它们的重量是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公斤。土豆包含...
double
只能表示2 ^ 64个不同的数字,这意味着:并非每个数字都在其中(0和1之间有无穷大的数字,更不用说在负无穷大和正无穷大之间了;显然,“无穷大无穷大”是远远超过2 ^ 64!)。计算机以二进制数计数,人类以十进制数计数,并且这两者是不相同的。