Java中的Currency Converter具有精度和冷凝问题

时间:2018-10-26 01:58:08

标签: java precision currency

我已经获得了一份用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;因此,我将拥有500个整数而不是5.00的两倍。但目前,我不确定进行的“适当”方法。

所以我来问你好人:D

我很高兴学到尽可能多的知识,感谢您的协助。

谢谢

更新: 我花了一些时间检查BigDecimal,然后它开始工作了。除了我现在的偏离量为1到10(可能非常大的数字会更多,但是我使用不同的数字进行的测试没有超过5次)。

在测试中,我将18765432.00日元转换为美元,汇率为1日元= 0.008907美元。根据我当时用来验证的网站,以美元计算的结果应该是879,701.24美元;但我的程序却能获得879,703.70美元。甚至我的科学计算器也得到了与Java程序相同的东西。

2 个答案:

答案 0 :(得分:0)

继续使用BigDecimal实施方法,就像使用BigDecimal一样,您将不会失去任何精度,但是如果您处理更大的数字,则使用DoubleDecimal可能会有损失的可能性。

请通过下面的stackoverflow链接获取有关BigDecimal的更多信息: Double vs. BigDecimal?

您处在正确的轨道上,继续摇摆并愉快地学习。

答案 1 :(得分:0)

这是另一种实现方式:

给出如下货币汇率列表:

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);**```

==============

包装测试;

导入java.util。*;

公共类CurrencyConvertor {     私人地图>映射=新的HashMap>();     私有布尔值bInit = false;     私人布尔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();
    }
}

}