繁体   English   中英

Java 中的货币转换器具有精度和压缩问题

[英]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.

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