当前位置: 首页 > 知识库问答 >
问题:

如何知道BigDecimal是否可以准确转换为浮点数或双精度?

简意
2023-03-14

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

  • <代码>字节值精确()

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

我阅读了方法FloatValue()douleValue()的OpenJDK源代码。两者似乎都分别回退到Float.parseFloat()Double.parseDouble(),它们可能返回正无穷大或负无穷大。例如,解析10,000个9s的字符串将返回正无穷大。据我所知,BigDecimal没有无穷大的内部概念。此外,将100个9s的字符串解析为Double给出了1.0E100,这不是无穷大,而是失去了精度。

什么是合理的实现?

我考虑了一种通过组合BigDecimal来实现双精度的解决方案。doubleValue(),BigDecial。toString(),双精度。parseDouble(字符串)Double。toString(double),但看起来很凌乱。我想在这里问一下,因为可能(必须!)更简单的解决方案。

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

共有1个答案

左丘成业
2023-03-14

通过读取文档,它对numTypeValueExact变量所做的一切就是检查是否存在小数部分,或者该值是否对于数字类型太大,并引发异常。

对于FloatValue()douleValue(),正在进行类似的溢出检查,但不是抛出异常,而是返回Double.POSITIVE_INFINITYDouble.NEGATIVE_INFINITY表示双精度和Float.POSITIVE_INFINITYFloat.NEGATIVE_INFINITY表示浮点数。

因此,浮点和double的精确方法的最合理(也是最简单)实现应该只检查转换是否返回正无穷大或负无穷大。

此外,请记住,BigDecimal旨在处理因对大型非理性使用浮动而导致的精度不足,因此正如@JB Nizet评论的那样,您可以添加到上面的另一个检查是将浮动转换回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));
}

上面使用compareTo而不是equals是有意的,以免对检查过于严格。equals仅当两个BigDecimal对象具有相同的值和比例(小数部分的大小)时才会评估为true,而compareTo在无关紧要时会忽略这种差异。例如2.0vs2.00

 类似资料:
  • 问题内容: 我有这个问题,我必须将公里转换成英里。我是一个新手程序员,所以请耐心等待。 到目前为止,这是我的代码: 它给我一个错误,说: 问题答案: 您正在尝试将a 设置为变量 要修复,请更改此行 至

  • 我有一个问题,我必须把公里转换成英里。我是一个新手程序员,所以请原谅我。 这是我到目前为止的代码: 它给我一个错误提示:

  • 问题内容: 我有一个浮点数组,我想将其转换为Java中的双精度数组。我知道迭代数组并创建一个新数组的明显方法。我希望Java在希望与double []一起工作的地方能够平稳地消化float [] …,但不能与此一起工作。进行这种转换的优雅,有效的方法是什么? 问题答案: 基本上 , 必须进行每个值的转换。两种数组类型之间没有隐式转换,因为在JITting之后用于处理它们的代码将有所不同- 它们具有

  • 我正在写一个基于无符号整数的图像类。我目前对8位和16位RGBA像素使用uint8_t和uint16_t缓冲,要从16位转换到8位,我只需将16位值除以std::numeric_limits 但是,如果我想要一个图像,每个RGBA分量都是64位无符号整数(我知道,这个数字高得离谱),我该如何在0和1之间找到一个浮点/双精度数,来表示我的像素值在0和最大uint64_t之间有多远呢?我认为转换为do

  • 问题内容: 我正在尝试对.3gpp音频文件执行快速傅立叶变换。该文件包含来自电话麦克风的44100kHz的5秒钟小录音。 出于显而易见的原因,我可以找到的每个Java FFT算法都只接受double [],float []或Complex []输入,但是我以字节数组的形式读取音频文件,因此我有点困惑我从这里去哪里。我唯一能找到的是上一个问题的答案: Android音频FFT使用音频记录检索特定频率

  • 在java中如何将BigDecimal转换为Double?我有一个要求,我们必须使用Double作为参数,但我们得到的是BigDecimal,所以我必须将BigDecimal转换为Double。