有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何知道BigDecimal是否可以精确地转换为float或double?

BigDecimal有一些有用的方法来保证无损转换:

  • byteValueExact()
  • shortValueExact()
  • intValueExact()
  • longValueExact()

但是,方法floatValueExact()doubleValueExact()不存在

我阅读了方法floatValue()doubleValue()的OpenJDK源代码。两者似乎分别回退到Float.parseFloat()Double.parseDouble(),这可能返回正无穷大或负无穷大。例如,解析10000个9的字符串将返回正无穷大。据我所知,BigDecimal没有无限的内部概念。此外,将100个9的字符串解析为double会得到1.0E100,这不是无穷大,但会丢失精度

什么是合理的实现floatValueExact()doubleValueExact()

我想通过组合{}、{}、{}和{}来找到一个{}解决方案,但它看起来很混乱。我想在这里提问,因为可能(必须!)这是一个更简单的解决方案

明确地说,我不需要高性能的解决方案


共 (1) 个答案

  1. # 1 楼答案

    readingthedocs开始,它对numTypeValueExact变量所做的一切就是检查分数部分的存在,或者该值对于数值类型是否太大,并引发异常

    至于^{}^{},正在进行类似的溢出检查,但它不是抛出异常,而是返回Double.POSITIVE_INFINITYDouble.NEGATIVE_INFINITY作为双精度,返回Float.POSITIVE_INFINITYFloat.NEGATIVE_INFINITY作为浮点数

    因此,对于float和double的exact方法,最合理(也是最简单)的实现应该只是检查转换是否返回POSITIVE_INFINITYNEGATIVE_INFINITY


    此外,,请记住,BigDecimal的设计是为了处理使用floatdouble处理大型非理性的精度不足,因此,与@JB Nizet{a7}一样,您可以添加到上面的另一个检查是将doublefloat转换回BigDecimal,以查看是否仍然得到相同的值。这应该证明转换是正确的

    下面是floatValueExact()的这种方法的样子:

    public static float floatValueExact(BigDecimal decimal) {
        float result = decimal.floatValue();
        if (!(Float.isNaN(result) || Float.isInfinite(result))) {
            if (new BigDecimal(String.valueOf(result)).compareTo(decimal) == 0) {
                return result;
            }
        }
        throw new ArithmeticException(String.format("%s: Cannot be represented as float", decimal));
    }
    

    使用^{}而不是上面的^{}是故意的,这样就不会对检查太严格^只有当两个BigDecimal对象具有相同的值和比例(小数部分的大小)时,{}才会计算为true,而compareTo在无关紧要的情况下会忽略这一差异。例如2.02.00