为什么我的代码比数学多输出一个?
Why is my code outputting one more than the math?
好的,所以我正在编写一个贷款计算器,其中在六个月的时间内从之前的金额中减去剩余贷款金额的 10%。问题不难,就是我写的代码好像……呃……智障。
import java.util.Scanner;
public class Program
{
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int amount = scanner.nextInt();
int payment;
for (int month = 0; month < 6; month++)
{
payment = amount / 10;
amount -= payment;
}
System.out.println(amount);
}
}
代码可以正常工作,但我计算了一下,amount 的输出正好比应有的多 1。是否有某种 Java 规则我还没有学会或什么?
当您处理整数时,可能会发生这种情况,因为“.”之后的部分。丢失了。让我们举例说明您的问题:
假设您的金额为 100,因此付款为:
100 / 10 = 10
90 / 10 = 9
81 / 10 = 8
73 / 10 = 7
66 / 10 = 6
60 / 10 = 6 -(这是您期望数字为 5 的地方,但这不是因为您在之前的所有计算中都丢失了小数部分)
输出:54
我个人认为对于这样的计算你应该使用双精度而不是整数
解决方案
以下代码将为您提供四舍五入到小数点后两位的结果。
正如评论中已经提到的那样,当您对整数执行 76 / 10 时,结果将为 7,因此小数部分将丢失。
所以在下面的解决方案中,我使用双精度而不是整数,并且按照您对货币的期望,将结果四舍五入到小数点后两位。
import java.util.Scanner;
public class Programm
{
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
double amount = scanner.nextDouble();
double payment;
try {
for (int month = 0; month < 6; month++)
{
payment = amount / 10;
amount -= payment;
amount = Math.round(100.0 * amount) / 100.0;
}
}catch(Exception e) {
System.out.println("Zero Divivided");
}
System.out.println(amount);
}
}
对于输入 100,代码生成结果 53.15
使用 Double 而不是 int,并且始终使用 2 个小数点,因为这是货币
public class Program {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
double amount = scanner.nextDouble();
double payment;
for (int month = 0; month < 6; month++) {
payment = amount / 10;
BigDecimal bd = new BigDecimal(payment).setScale(2, RoundingMode.HALF_UP);
amount -= bd.doubleValue();
}
System.out.println(amount);
}
}
好问题的特点之一是包含您的输入和输出。在您的情况下,每行输入都会产生一行输出。你应该在你的问题中输入一个 3 列 table。第一列应该是输入整数,第二列应该是预期的输出值(您的定义),第三列应该是代码为该输入生成的值。一旦达到可以生成此 table 的程度,就可以构建测试了。
就您的代码而言,您可以使用类似的东西对其进行测试,而无需学习任何有关 JUnit 的知识。下面的脚本非常简单,并且使用了您无论如何都应该学习的工具。嗯,也就是说,如果您打算在余下的职业生涯中使用真正的操作系统。您可以使用这些工具来测试许多代码,而不管其语言如何。
这是针对您的特定程序的测试 shell 脚本:
javac Program.java
if [ $? -ne 0 ]; then
exit 1;
fi
while read line; do
echo $line > tmp
java Program < tmp
done < test.dat > test.out
diff test.out test.spec
这是执行它的一种方法:
$ sh test.sh
这是您的代码由 运行 脚本生成的内容:
$ cat test.out
54
533
5315
53145
268
2658
26573
265721
如果所有测试都通过,则脚本不会产生任何输出。这是该脚本使用的测试数据。
$ cat test.dat
100
1000
10000
100000
500
5000
50000
500000
这里是这些数据输出的规范,因为您说您的代码产生的输出正好比您预期的多一个。
cat test.spec
53
532
5314
53144
267
2657
26572
265720
这是脚本生成的内容,因为代码不满足您的规范:
$ sh test.sh
1,8c1,8
< 54
< 533
< 5315
< 53145
< 268
< 2658
< 26573
< 265721
---
> 53
> 532
> 5314
> 53144
> 267
> 2657
> 26572
> 265720
如果您在程序的两个地方将 int
更改为 double
,那么脚本将生成以下内容:
$ sh test.sh
1,8c1,8
< 53.1441
< 531.441
< 5314.41
< 53144.1
< 265.7205
< 2657.205
< 26572.05
< 265720.5
---
> 53
> 532
> 5314
> 53144
> 267
> 2657
> 26572
> 265720
如果你想 floor
输出值,那么你可以使用 String.format
,也许它会符合规范。在这种情况下不会,因为我盲目地遵循您的定义(比预期多 1 个)。但是,如果您接受测试驱动开发,您将会走得更远。
好的,所以我正在编写一个贷款计算器,其中在六个月的时间内从之前的金额中减去剩余贷款金额的 10%。问题不难,就是我写的代码好像……呃……智障。
import java.util.Scanner;
public class Program
{
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int amount = scanner.nextInt();
int payment;
for (int month = 0; month < 6; month++)
{
payment = amount / 10;
amount -= payment;
}
System.out.println(amount);
}
}
代码可以正常工作,但我计算了一下,amount 的输出正好比应有的多 1。是否有某种 Java 规则我还没有学会或什么?
当您处理整数时,可能会发生这种情况,因为“.”之后的部分。丢失了。让我们举例说明您的问题: 假设您的金额为 100,因此付款为:
100 / 10 = 10
90 / 10 = 9
81 / 10 = 8
73 / 10 = 7
66 / 10 = 6
60 / 10 = 6 -(这是您期望数字为 5 的地方,但这不是因为您在之前的所有计算中都丢失了小数部分)
输出:54
我个人认为对于这样的计算你应该使用双精度而不是整数
解决方案
以下代码将为您提供四舍五入到小数点后两位的结果。
正如评论中已经提到的那样,当您对整数执行 76 / 10 时,结果将为 7,因此小数部分将丢失。
所以在下面的解决方案中,我使用双精度而不是整数,并且按照您对货币的期望,将结果四舍五入到小数点后两位。
import java.util.Scanner;
public class Programm
{
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
double amount = scanner.nextDouble();
double payment;
try {
for (int month = 0; month < 6; month++)
{
payment = amount / 10;
amount -= payment;
amount = Math.round(100.0 * amount) / 100.0;
}
}catch(Exception e) {
System.out.println("Zero Divivided");
}
System.out.println(amount);
}
}
对于输入 100,代码生成结果 53.15
使用 Double 而不是 int,并且始终使用 2 个小数点,因为这是货币
public class Program {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
double amount = scanner.nextDouble();
double payment;
for (int month = 0; month < 6; month++) {
payment = amount / 10;
BigDecimal bd = new BigDecimal(payment).setScale(2, RoundingMode.HALF_UP);
amount -= bd.doubleValue();
}
System.out.println(amount);
}
}
好问题的特点之一是包含您的输入和输出。在您的情况下,每行输入都会产生一行输出。你应该在你的问题中输入一个 3 列 table。第一列应该是输入整数,第二列应该是预期的输出值(您的定义),第三列应该是代码为该输入生成的值。一旦达到可以生成此 table 的程度,就可以构建测试了。
就您的代码而言,您可以使用类似的东西对其进行测试,而无需学习任何有关 JUnit 的知识。下面的脚本非常简单,并且使用了您无论如何都应该学习的工具。嗯,也就是说,如果您打算在余下的职业生涯中使用真正的操作系统。您可以使用这些工具来测试许多代码,而不管其语言如何。
这是针对您的特定程序的测试 shell 脚本:
javac Program.java
if [ $? -ne 0 ]; then
exit 1;
fi
while read line; do
echo $line > tmp
java Program < tmp
done < test.dat > test.out
diff test.out test.spec
这是执行它的一种方法:
$ sh test.sh
这是您的代码由 运行 脚本生成的内容:
$ cat test.out
54
533
5315
53145
268
2658
26573
265721
如果所有测试都通过,则脚本不会产生任何输出。这是该脚本使用的测试数据。
$ cat test.dat
100
1000
10000
100000
500
5000
50000
500000
这里是这些数据输出的规范,因为您说您的代码产生的输出正好比您预期的多一个。
cat test.spec
53
532
5314
53144
267
2657
26572
265720
这是脚本生成的内容,因为代码不满足您的规范:
$ sh test.sh
1,8c1,8
< 54
< 533
< 5315
< 53145
< 268
< 2658
< 26573
< 265721
---
> 53
> 532
> 5314
> 53144
> 267
> 2657
> 26572
> 265720
如果您在程序的两个地方将 int
更改为 double
,那么脚本将生成以下内容:
$ sh test.sh
1,8c1,8
< 53.1441
< 531.441
< 5314.41
< 53144.1
< 265.7205
< 2657.205
< 26572.05
< 265720.5
---
> 53
> 532
> 5314
> 53144
> 267
> 2657
> 26572
> 265720
如果你想 floor
输出值,那么你可以使用 String.format
,也许它会符合规范。在这种情况下不会,因为我盲目地遵循您的定义(比预期多 1 个)。但是,如果您接受测试驱动开发,您将会走得更远。