[英]Currency Converter in Java having precision and condensing issues
我收到了一份要用 Java 编写的作业。
我们将开发一个货币兑换应用程序,询问他们兑换的货币、所述货币的数量以及他们希望兑换的货币。
该说明指出我们应该包括 4 种货币来转换。
我很早就完成了作业,我去给我的教授看,她注意到了一些问题。 她喜欢代码的组织和清晰度,但她认为我可以让它更小一点,并解决我在十进制精度方面遇到的问题。
关于让它更短,她的主要论点是我有 7 个常量来保持汇率。 我为此感到相当自豪,因为对于每种可能的组合,7 个费率比 12 个单独费率要短得多。 代码如下。
// Conversion Rates - START (as of October 14, 2018 @ 1:03 AM)
// Rates obtained from exchange-rates.org
private final double USD_TO_USD = 1;
//Convert to United States Dollars
private final double CAD_TO_USD = 0.76792;
private final double EUR_TO_USD = 1.1407;
private final double YEN_TO_USD = 0.008923;
//Convert from United States Dollars
private final double USD_TO_CAD = 1.3022;
private final double USD_TO_EUR = 0.87662;
private final double USD_TO_YEN = 112.06;
// Conversion Rates - END
我的方法背后的思考过程是将所有东西都转换为美元,然后从美元转换为目标货币。 我不确定如何进一步浓缩,所以这是我遇到的问题之一。
我遇到的主要问题是精度。 由于该课程主要基于商业数学,因此这些程序通常用于转换数百万/十亿的货币。 我知道 double 已经有它自己的精度继承问题,但我不确定要使用哪些其他数据类型。 我遇到了 BigDecimal,我会在发布这个后研究一下。
据我了解,汇率中的小数位数会直接影响结果的精度。 汇率右侧的数字越多; 更好。 我是否应该养成包含大量小数点的习惯,以便很难出现精度问题? 或者使用 BigDecimal 通常会解决问题。
我已经考虑放弃使用 double 并使用 int 代替; 所以不是双重持有 5.00,我会有一个持有 500 的整数; 但在这一点上,我不确定“正确”的继续方式。
所以我是来问你们好人的 :D
我很高兴尽可能多地学习,因此感谢任何帮助。
谢谢
更新:我花了一些时间来检查 BigDecimal,我让它工作了; 除了我现在减少了 1 到 10 的数量(在非常非常大的数字中可能更多,但我没有用不同的数字测试它超过 5 次)。
在我的测试中,我将 98765432.00 日元转换为美元,汇率为 1 日元 = 0.008907 美元。 根据我当时用来验证的网站——以美元计算的结果应该是USD$879,701.24; 但我的程序获得了 879,703.70 美元。 甚至我的科学计算器也得到了与我的 java 程序得到的相同的结果。
继续使用 BigDecimal 的方法,就像使用 BigDecimal 一样,您不会失去任何精度,但是使用 double 时,在处理更大的数字时有可能会丢失。
请通过下面的 stackoverflow 链接获得更多关于 BigDecimal 的想法: Double vs. BigDecimal?
你走在正确的轨道上,不断摇摆,快乐学习。
这是另一个实现:
给定一个像这样的货币汇率列表:
USD/GBP => 0.75
GBP/AUD => 1.7
AUD/JPY => 90
GBP/JPY => 150
JPY/INR => 0.6
Write a method
double convert(String sourceCurrency, double amount, String destCurrency);
==============
package test;
import java.util.*;
public class CurrencyConvertor {
private Map<String, Map<String, Double>> mapping = new HashMap<String, Map<String, Double>>();
private boolean bInit = false;
private boolean bFound = false;
double convert(String src, double amount, String dst) throws Exception {
if (src.equals(dst))
return amount;
if (!bInit) {
init();
bInit = true;
}
bFound = false;
if (mapping.get(src) == null) {
throw new Exception("Invalid conversion");
}
List<String> visited = new ArrayList<String>();
visited.add(src);
double d1 = getRate(visited, src, dst, 1);
if (bFound)
return d1 * amount;
throw new Exception("No mapping invalid conversion");
}
private double getRate(List<String> visited, String src, String dst, double rate) throws Exception {
if (bFound == true) {
return rate;
}
if (mapping.get(src).get(dst) != null) {
bFound = true;
return rate * mapping.get(src).get(dst);
}
double origRate = rate;
for (String sInt : mapping.get(src).keySet()) {
if (visited.contains(sInt)) {
continue;
}
visited.add(sInt);
rate = getRate(visited, sInt, dst, rate * mapping.get(src).get(sInt));
if (bFound == true) {
return rate;
}
visited.remove(sInt);
rate = origRate;
}
return origRate;
}
private void init() {
// Invalid case data, EUR to INR
insert("EUR", "USD", 1.2);
insert("USD", "EUR", 0.75);
insert("YEN", "INR", 1.2);
insert("INR", "YEN", 0.75);
// Valid case data, EUR to INR
// insert("EUR", "USD", 1.2);
// insert("USD", "GBP", 0.75);
// insert("GBP", "AUD", 1.7);
// insert("AUD", "JPY", 90);
// insert("GBP", "JPY", 150);
// insert("JPY", "INR", 0.6);
//
// insert("USD", "EUR", 1.0/1.2);
// insert("GBP", "USD", 1.0/0.75);
// insert("AUD", "GBP", 1.0/1.7);
// insert("JPY", "AUD", 1.0/90);
// insert("JPY", "GBP", 1.0/150);
// insert("INR", "JPY", 1.0/0.6);
}
private void insert(String src, String dst, double rate) {
if (mapping.get(src) == null) {
Map<String, Double> map = new HashMap<String, Double>();
map.put(dst, rate);
mapping.put(src, map);
} else if (mapping.get(src).get(dst) == null) {
mapping.get(src).put(dst, rate);
}
}
public static void main(String args[]) {
try {
double d = new CurrencyConvertor().convert("EUR", 100, "INR");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.