简体   繁体   English

为什么我的代码输出比数学多一个?

[英]Why is my code outputting one more than the math?

Okay, so I'm writing a loan calculator where 10% of the remaining amount of the loan is subtracted from the previous amount over the course of six months.好的,所以我正在编写一个贷款计算器,其中在六个月的过程中从之前的金额中减去 10% 的贷款余额。 The problem isn't difficult, it's that the code I wrote seems to be... uhm... retarded.问题不难,就是我写的代码好像……呃……智障。

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);
        
    }
}

The code sorta works, but I did the math and the output of amount is exactly 1 more than it should be.代码排序有效,但我做了数学计算,output 的数量正好比应有的多 1。 Is there some kind of Java rule that I just haven't learned yet or what?是否有某种我尚未学习的 Java 规则或什么?

When you work on integers it might happens because the part after '.'当您处理整数时,它可能会发生,因为 '.' 之后的部分。 is lost.丢失了。 Lets make an example of your problem: Assume that you have amount 100 so the payments are:让我们举个例子来说明您的问题:假设您的金额为 100,因此付款为:

100 / 10 = 10 100 / 10 = 10

90 / 10 = 9 90 / 10 = 9

81 / 10 = 8 81 / 10 = 8

73 / 10 = 7 73 / 10 = 7

66 / 10 = 6 66 / 10 = 6

60 / 10 = 6 - (this is where you expect that the number will be 5 but it is not because you lose decimal part in all previous calculations) 60 / 10 = 6 - (这是您期望数字为 5 的地方,但这并不是因为您在之前的所有计算中都丢失了小数部分)

Output: 54 Output:54

Personally I think that for such calculation you should use double instead of integer我个人认为,对于这样的计算,你应该使用 double 而不是 integer

Solution解决方案

The following code will give you the result rounded on two decimal places.以下代码将为您提供四舍五入到小数点后两位的结果。

As in the commentarys already mentioned when you do 76 / 10 on an integer the result will be 7 so the decimal part will be lost.正如评论中已经提到的,当您在 integer 上执行 76 / 10 时,结果将为 7,因此小数部分将丢失。

So in the solution below I used double instead of integer and I rounded up the result on two decimal places as you expect from currencys.因此,在下面的解决方案中,我使用了 double 而不是 integer,并且按照您对货币的期望,我将结果四舍五入到小数点后两位。

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);
        
    }
}

For the input of 100 the code produces the result 53.15对于 100 的输入,代码生成结果 53.15

Use Double instead of int, and always use 2 decimal points since this is the currency使用 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);
}

} }

One of the hallmarks of a good question is to include your inputs and your outputs.一个好问题的标志之一是包括你的输入和输出。 In your case, each line of input results in a single line of output.在您的情况下,每行输入都会产生一行 output。 You should put in your question a 3-column table.你应该在你的问题中加入一个 3 列表。 The first column should be the input integer, the second column should be the expected output value (your definition), and the third column should be what the code produced for that input.第一列应该是输入 integer,第二列应该是预期的 output 值(您的定义),第三列应该是为该输入生成的代码。 Once you get to the point where you can produce this table, you can construct your tests.一旦达到可以生成此表的程度,就可以构建测试。

As your code stands, you can test it with something like this, without having to learn anything about JUnit.就您的代码而言,您可以使用类似这样的方式对其进行测试,而无需了解有关 JUnit 的任何信息。 The script below is quite simple and utilizes tools that you should be learning anyway.下面的脚本非常简单,并且使用了您无论如何都应该学习的工具。 Well, that is, if you plan to use a real operating system for the rest of your career.好吧,也就是说,如果你打算为你职业生涯的 rest 使用真正的操作系统。 You can use these tools to test much code regardless of its language.无论语言如何,您都可以使用这些工具测试大量代码。

Here is a test shell script for your particular program:这是您的特定程序的测试 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

Here is one way you execute it:这是您执行它的一种方法:

$ sh test.sh

Here is what your code produces by running the script:以下是您的代码通过运行脚本生成的内容:

$ cat test.out
54
533
5315
53145
268
2658
26573
265721

If all tests pass, then the script produces no output.如果所有测试都通过,则脚本不会生成 output。 Here is the test data used by that script.这是该脚本使用的测试数据。

$ cat test.dat
100
1000
10000
100000
500
5000
50000
500000

Here is a specification for the outputs of those data given the fact that you said your code produces output that is exactly one more than what you expect.这是这些数据输出的规范,因为您说您的代码产生的 output 恰好比您预期的多一个。

cat test.spec
53
532
5314
53144
267
2657
26572
265720

This is what the script produces, since the code isn't satisfying your specification:这是脚本产生的,因为代码不满足您的规范:

$ sh test.sh
1,8c1,8
< 54
< 533
< 5315
< 53145
< 268
< 2658
< 26573
< 265721
---
> 53
> 532
> 5314
> 53144
> 267
> 2657
> 26572
> 265720

If you change int to double in two places in your program, then this is what the script produces:如果您在程序中的两个位置将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

If you want to floor the output values then you can use String.format and perhaps it would match the spec.如果您想降低floor值,那么您可以使用String.format ,也许它会符合规范。 It won't in this case because I'm blindly following your definition (1 more than desired).在这种情况下不会,因为我盲目地遵循您的定义(比期望的多 1 个)。 But you'll go far if you embrace Test Driven Development.但是,如果您接受测试驱动开发,您将远远超过 go。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM