gst*_*low -1 java string currency
在服务器上我接受String作为参数.这个字符串代表钱.
它可能是(例如)
0
12
12,
12,34
,12
Run Code Online (Sandbox Code Playgroud)
现在我这样削减它:
long centAmount = (long) (NumberFormat.getInstance(Locale.FRANCE).parse(outSum).doubleValue() * 100)
Run Code Online (Sandbox Code Playgroud)
我担心我会在某处丢失一分钱.
请告知如何重写我的代码.
当你使用(long)它时截断数字.这意味着0.999999999999999将被截断到0哪里将失去你在这里和那里的一分钱.更好的方法是使用舍入.
double input = NumberFormat.getInstance(Locale.FRANCE).parse(outSum).doubleValue();
long centAmount = Math.round(input * 100);
Run Code Online (Sandbox Code Playgroud)
这将适用于价值高达70万亿美元的价值.如果您需要准确存储更大的数量,则需要使用BigDecimal和BigInteger.
使用BigDecimal的一个优点是它会提醒你什么时候应该使用舍入(并不总是,但如果你不确定它不容易出错)缺点是代码更加麻烦.
如果你使用BigDecimal,你可以这样做
DecimalFormat df = (DecimalFormat) NumberFormat.getInstance(Locale.FRANCE);
df.setParseBigDecimal(true);
BigDecimal bd = (BigDecimal) df.parseObject(outSum);
BigDecimal bd100 = bd.multiply(BigDecimal.valueOf(100))
.setScale(0, RoundingMode.HALF_UP);
long centAmount = bd100.longValue();
Run Code Online (Sandbox Code Playgroud)
添加一个简单的例子,说明为什么BigDecimal不能解决所有问题,但它确实隐藏了它们.
BigDecimal add = new BigDecimal("1.00")
.divide(BigDecimal.valueOf(3), 2, BigDecimal.ROUND_HALF_UP)
.multiply(BigDecimal.valueOf(3)).add(new BigDecimal("0.01"));
System.out.println(add);
double add2 = 1.0 / 3 * 3 + 0.01;
System.out.println(add2);
Run Code Online (Sandbox Code Playgroud)
这打印
1.00
1.01
Run Code Online (Sandbox Code Playgroud)
哪一个更容易出错,你可以争论任何一种方式(这可能是基于你的团队,他们发现哪些更容易出错),但哪一个更难理解它想要做什么?
我对BigDecimal的问题是黑白评估double是有缺陷的,BigDecimal会解决你所有的问题,实际上,你得到了所有相同的问题但是使用BigDecimal它们可能更难发现,所以你可能永远不会知道你有问题.
有了双倍,如果你看到1.0999999999999998你认为,那看起来不对,但有了BigDecimal,你可能会看到1.00并认为看起来不错.