在Java中将字符串转换为BigDecimal

96

我正在将XML中的货币读入Java。

String currency = "135.69";

当我将它转换为 BigDecimal 时,我得到的结果是:

 System.out.println(new BigDecimal(135.69));

输出:

135.68999999999999772626324556767940521240234375.
为什么输出这么多数字?我该如何避免这种情况?我只想让它输出135.69。

你确定 currency 的类型是字符串吗?而且你只读取了字符串的值? - Rohit Jain
可能是设置BigDecimal的特定精度的重复问题。 - Robert Moskal
5
你的货币不是一个 String,你可以使用 BigDecimal 构造函数,并将一个 String 作为参数传入。 - fge
可能有很多解决方案,但你知道它为什么会发生吗?如果不知道,请阅读此文:http://effbot.org/pyfaq/why-are-floating-point-calculations-so-inaccurate.htm - Cem Kalyoncu
7个回答

177

BigDecimal(double) 构造函数可能会有不可预测的行为。最好使用 BigDecimal(String) 或 BigDecimal.valueOf(double)。

System.out.println(new BigDecimal(135.69)); //135.68999999999999772626324556767940521240234375
System.out.println(new BigDecimal("135.69")); // 135.69
System.out.println(BigDecimal.valueOf(135.69)); // 135.69

BigDecimal(double)的文档详细解释了:

  1. 此构造方法的结果可能会有些不可预测。人们可能会认为在Java中编写new BigDecimal(0.1)将创建一个与0.1完全相等(无标度值为1,标度为1)的BigDecimal,但实际上它等于0.1000000000000000055511151231257827021181583404541015625。这是因为0.1不能准确地表示为double(或者说,不能准确地表示为任何有限长度的二进制分数)。因此,传递给构造函数的值并不完全等于0.1,尽管表象如此。
  2. 另一方面,String构造函数则是完全可预测的:编写new BigDecimal("0.1")将创建一个完全等于0.1的BigDecimal,正如人们所期望的那样。因此,通常建议使用String构造函数而不是此构造函数。
  3. 当必须将double用作BigDecimal的源时,请注意,此构造函数提供精确转换;它不会像使用Double.toString(double)方法将double转换为字符串,然后使用BigDecimal(String)构造函数那样得到相同的结果。要获得该结果,请使用静态的valueOf(double)方法。

如果您在服务中只收到一个字符串,但它可能是整数、双精度等类型,您会怎么说? - PeterS
2
在这种情况下,我会使用new BigDecimal("string_value")。这样,它将对整数和小数都能正确地运行。 - Marlon Patrick

39
String currency = "135.69";
System.out.println(new BigDecimal(currency));

//will print 135.69

1
不良实践是使用构造函数来实例化 "String"、"BigInteger"、"BigDecimal" 和基本包装类。https://rules.sonarsource.com/java/RSPEC-2129 - Nate Getch
@NateGetch(我知道这是旧的),但你有读过你提供的链接吗?它本身将new BigDecimal("42.0")列为符合规范的解决方案!它提到的应该使用的替代方案是自动装箱(无法与BigDecimal一起使用)和valueOf()(没有接受String参数的方法)。 - undefined

4
你将 135.69 存储为字符串类型的货币。但是在使用 new BigDecimal() 时,你又传递了 135.69(双精度浮点数)而不是变量 currency。因此,你会在输出中看到许多数字。 如果你传递 currency 变量,你的输出将是 135.69。

3

我可以补充一些内容。如果您正在使用货币,应该使用Scale(2),并且可能需要确定一个四舍五入的方法。


3

BigDecimal b = BigDecimal.valueOf(d);

import java.math.*; 

public class Test { 

    public static void main(String[] args) 
    { 

        // Creating a Double Object 
        Double d = new Double("785.254"); 

        /// Assigning the bigdecimal value of ln to b 
        BigDecimal b = BigDecimal.valueOf(d); 

        // Displaying BigDecimal value 
        System.out.println("The Converted BigDecimal value is: " + b); 
    } 
}

2

Spring Framework提供了一个出色的utils类来实现这一点。

Utils类:NumberUtils

将String转换为BigDecimal -

NumberUtils.parseNumber("135.00", BigDecimal.class);

-9

大家好,你不能直接将字符串转换为BigDecimal。

你需要先将它转换成长整型,然后再转换为BigDecimal。

String currency = "135.69"; 
Long rate1=Long.valueOf((currency ));            
System.out.println(BigDecimal.valueOf(rate1));

(1) "你不能直接将字符串转换为BigDecimal"- 当然可以:new BigDecimal("135.69"); (2) "将其转换为long类型" - 对于像135.69这样的小数,这是不可能的。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接