通过文本文件读取货币金额并计算票据面额
Reading in monetary amounts by text file & calculating bill denominations
我应该将文本文件读入 java 程序,在 java 文件中添加货币金额,然后确定如何支付每个总金额(读取 $20、$10、$5 ...)。我在如何处理分离文本文件的每一行以进行单独计算时遇到问题。
这是我要导入的文本文件:
Class1 9.30 7.44 5.32 3.33
Class2 2.22
Class3 7.33 4.44 3.56
Class4 15.67 12.02 10.33 8.87
Class5 4.44 3.33 2.22 1.11
我应该不仅为每个值显示解决方案,而且为每个 class 显示解决方案。我假设需要某种 for 循环,但我无法弄清楚。
public static void main(String[] args) throws FileNotFoundException, IOException {
FileReader file = new FileReader("C:\Users\idhit\Desktop\amounts.txt");
BufferedReader bf = new BufferedReader(file);
String st = bf.readLine();
double sum = 0;
double c1total = 0;
double c2total = 0;
double c3total = 0;
double c4total = 0;
double c5total = 0;
while ((st = bf.readLine()) != null) {
StringTokenizer stn = new StringTokenizer(st);
String rn = stn.nextToken();
String name = stn.nextToken();
double c1 = Double.parseDouble(stn.nextToken());
double c2 = Double.parseDouble(stn.nextToken());
double c3 = Double.parseDouble(stn.nextToken());
double c4 = Double.parseDouble(stn.nextToken());
double c5 = Double.parseDouble(stn.nextToken());
}
double value = scan.nextDouble();
int valueIntegral = (int) value;
int valueFractional = (int) Math.round(100 * value - 100 * valueIntegral);
// Integral values
int hundred = valueIntegral / 100;
int fifty = (valueIntegral % 100) / 50;
int twenty = ((valueIntegral % 100) % 50) / 20;
int ten = (((valueIntegral % 100) % 50) % 20) / 10;
int five = ((((valueIntegral % 100) % 50) % 20) % 10) / 5;
int one = (((((valueIntegral % 100) % 50) % 20) % 10) % 5) / 1;
// Fractional values
int quarter = valueFractional / 25;
int dime = (valueFractional % 25) / 10;
int nickel = ((valueFractional % 25) % 10) / 5;
int penny = (((valueFractional % 25) % 10) % 5) / 1;
System.out.println(hundred + " hundred dollar bills\n" + fifty + " fifty dollar bills\n" + twenty
+ " twenty dollar bills\n" + ten + " ten dollar bills\n" + five + " five dollar bills\n" + one
+ " one dollar bills\n" + quarter + " quarters\n" + dime + " dimes\n" + nickel + " nickels\n" + penny
+ " pennies");
}
您的方向是正确的,但是要根据名称为每个 class 分配总数,您需要一些条件。假设您的 bufferedReader
读取第 1 行,即
Class1 9.30 7.44 5.32 3.33
从 StringTokenizer 中,您可以获得每个 class 的名称和总金额。
每次调用 .nextToken()
时,它都会读取下一个分隔符。在您的情况下,它是空格。首先 .nextToken()
将读作 Class1
。第二个将显示为 9.30
等等...
Class 1: 25.39
从这里开始,如果名称是 Class1
,您可以将总计输入 c1total
。敲响任何铃铛?是的,你猜对了。你会在这里使用 if 语句。由于您有 5 个 classes,因此您有 5 个 if 语句。你的每一次都将处理每一行并使用 if 语句将其分配给正确的变量。
我建议您尝试我上面写的内容,但是我以不同的方式做了同样的事情,只是为了给您一个洞察力,以及如何以不同的方式甚至可能更好地对相同的事情进行编程。
编辑: 就像 DawoodibnKareem 建议的那样。 StringTokenizer
是遗留的,不应使用。我已经更新了代码。它现在使用 split 和 BigDecimal 而不是 double。
// Instead of 5 variables I created an array to store data
BigDecimal[] classTotal = new BigDecimal[5];
String line;
while ((line = bufferedReader.readLine()) != null) {
String[] lineSplit = line.split("\s+");
// Class1 9.30 7.44 5.32 3.33 would become
// [Class1, 9.30, 7.44, 5.32, 3.33]
String name = lineSplit[0];
switch (name) {
case "Class1":
classTotal[0] = getSum(lineSplit);
break;
case "Class2":
classTotal[1] = getSum(lineSplit);
break;
case "Class3":
classTotal[2] = getSum(lineSplit);
break;
case "Class4":
classTotal[3] = getSum(lineSplit);
break;
case "Class5":
classTotal[4] = getSum(lineSplit);
break;
}
}
bufferedReader.close();
for (int i = 0; i < classTotal.length; i++) {
System.out.println("Class " + (i + 1) + " : " + classTotal[i]);
}
public static BigDecimal getSum(String[] line) {
BigDecimal sum = new BigDecimal(0);
// Iterating from index 1 because 0 index contains name
for (int i = 1; i < line.length; i++) {
BigDecimal valueBigDecimal = new BigDecimal(line[i]);
sum = sum.add(valueBigDecimal);
}
return sum;
}
输出:
Class 1 : 25.39
Class 2 : 2.22
Class 3 : 15.33
Class 4 : 46.89
Class 5 : 11.10
输出:(如果我使用 double 而不是 BigDecimal)
Class 1 : 25.39
Class 2 : 2.22
Class 3 : 15.33
Class 4 : 46.88999999999999
Class 5 : 11.1
请注意某些值是如何关闭的,尤其是 Class 4
应该是 46.89
。
这是因为 Java 中的 float 和 double 基本类型是 浮点数 数字,其中数字存储为分数和指数的二进制表示。浮点数有时(安全地假设 "most of the time")无法 return 数字的精确表示。因此你得到 46.88999999999999
而不是 46.89
。这就是为什么 double/float 在计算货币方面被认为是可怕的。为了避免这个问题,我们必须使用 BigDecimal。特别是在您进一步对 double 执行计算只会降低精度的情况下。
我应该将文本文件读入 java 程序,在 java 文件中添加货币金额,然后确定如何支付每个总金额(读取 $20、$10、$5 ...)。我在如何处理分离文本文件的每一行以进行单独计算时遇到问题。
这是我要导入的文本文件:
Class1 9.30 7.44 5.32 3.33
Class2 2.22
Class3 7.33 4.44 3.56
Class4 15.67 12.02 10.33 8.87
Class5 4.44 3.33 2.22 1.11
我应该不仅为每个值显示解决方案,而且为每个 class 显示解决方案。我假设需要某种 for 循环,但我无法弄清楚。
public static void main(String[] args) throws FileNotFoundException, IOException {
FileReader file = new FileReader("C:\Users\idhit\Desktop\amounts.txt");
BufferedReader bf = new BufferedReader(file);
String st = bf.readLine();
double sum = 0;
double c1total = 0;
double c2total = 0;
double c3total = 0;
double c4total = 0;
double c5total = 0;
while ((st = bf.readLine()) != null) {
StringTokenizer stn = new StringTokenizer(st);
String rn = stn.nextToken();
String name = stn.nextToken();
double c1 = Double.parseDouble(stn.nextToken());
double c2 = Double.parseDouble(stn.nextToken());
double c3 = Double.parseDouble(stn.nextToken());
double c4 = Double.parseDouble(stn.nextToken());
double c5 = Double.parseDouble(stn.nextToken());
}
double value = scan.nextDouble();
int valueIntegral = (int) value;
int valueFractional = (int) Math.round(100 * value - 100 * valueIntegral);
// Integral values
int hundred = valueIntegral / 100;
int fifty = (valueIntegral % 100) / 50;
int twenty = ((valueIntegral % 100) % 50) / 20;
int ten = (((valueIntegral % 100) % 50) % 20) / 10;
int five = ((((valueIntegral % 100) % 50) % 20) % 10) / 5;
int one = (((((valueIntegral % 100) % 50) % 20) % 10) % 5) / 1;
// Fractional values
int quarter = valueFractional / 25;
int dime = (valueFractional % 25) / 10;
int nickel = ((valueFractional % 25) % 10) / 5;
int penny = (((valueFractional % 25) % 10) % 5) / 1;
System.out.println(hundred + " hundred dollar bills\n" + fifty + " fifty dollar bills\n" + twenty
+ " twenty dollar bills\n" + ten + " ten dollar bills\n" + five + " five dollar bills\n" + one
+ " one dollar bills\n" + quarter + " quarters\n" + dime + " dimes\n" + nickel + " nickels\n" + penny
+ " pennies");
}
您的方向是正确的,但是要根据名称为每个 class 分配总数,您需要一些条件。假设您的 bufferedReader
读取第 1 行,即
Class1 9.30 7.44 5.32 3.33
从 StringTokenizer 中,您可以获得每个 class 的名称和总金额。
每次调用 .nextToken()
时,它都会读取下一个分隔符。在您的情况下,它是空格。首先 .nextToken()
将读作 Class1
。第二个将显示为 9.30
等等...
Class 1: 25.39
从这里开始,如果名称是 Class1
,您可以将总计输入 c1total
。敲响任何铃铛?是的,你猜对了。你会在这里使用 if 语句。由于您有 5 个 classes,因此您有 5 个 if 语句。你的每一次都将处理每一行并使用 if 语句将其分配给正确的变量。
我建议您尝试我上面写的内容,但是我以不同的方式做了同样的事情,只是为了给您一个洞察力,以及如何以不同的方式甚至可能更好地对相同的事情进行编程。
编辑: 就像 DawoodibnKareem 建议的那样。 StringTokenizer
是遗留的,不应使用。我已经更新了代码。它现在使用 split 和 BigDecimal 而不是 double。
// Instead of 5 variables I created an array to store data
BigDecimal[] classTotal = new BigDecimal[5];
String line;
while ((line = bufferedReader.readLine()) != null) {
String[] lineSplit = line.split("\s+");
// Class1 9.30 7.44 5.32 3.33 would become
// [Class1, 9.30, 7.44, 5.32, 3.33]
String name = lineSplit[0];
switch (name) {
case "Class1":
classTotal[0] = getSum(lineSplit);
break;
case "Class2":
classTotal[1] = getSum(lineSplit);
break;
case "Class3":
classTotal[2] = getSum(lineSplit);
break;
case "Class4":
classTotal[3] = getSum(lineSplit);
break;
case "Class5":
classTotal[4] = getSum(lineSplit);
break;
}
}
bufferedReader.close();
for (int i = 0; i < classTotal.length; i++) {
System.out.println("Class " + (i + 1) + " : " + classTotal[i]);
}
public static BigDecimal getSum(String[] line) {
BigDecimal sum = new BigDecimal(0);
// Iterating from index 1 because 0 index contains name
for (int i = 1; i < line.length; i++) {
BigDecimal valueBigDecimal = new BigDecimal(line[i]);
sum = sum.add(valueBigDecimal);
}
return sum;
}
输出:
Class 1 : 25.39
Class 2 : 2.22
Class 3 : 15.33
Class 4 : 46.89
Class 5 : 11.10
输出:(如果我使用 double 而不是 BigDecimal)
Class 1 : 25.39
Class 2 : 2.22
Class 3 : 15.33
Class 4 : 46.88999999999999
Class 5 : 11.1
请注意某些值是如何关闭的,尤其是 Class 4
应该是 46.89
。
这是因为 Java 中的 float 和 double 基本类型是 浮点数 数字,其中数字存储为分数和指数的二进制表示。浮点数有时(安全地假设 "most of the time")无法 return 数字的精确表示。因此你得到 46.88999999999999
而不是 46.89
。这就是为什么 double/float 在计算货币方面被认为是可怕的。为了避免这个问题,我们必须使用 BigDecimal。特别是在您进一步对 double 执行计算只会降低精度的情况下。