Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/370.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java中浮点类型的转换和计算_Java_Ieee 754 - Fatal编程技术网

Java中浮点类型的转换和计算

Java中浮点类型的转换和计算,java,ieee-754,Java,Ieee 754,我试图在Java中学习更多关于浮点、双精度和大小数的知识。我想确切地知道浮点数在每种类型中是如何表示的,例如,浮点数使用2^,大小数使用10^加上刻度(32位)和无刻度值(任意精度) 我用这三种类型组合了简单的计算,并对每种类型进行了对话,结果相当混乱。我希望得到一些提示,说明为什么唯一正确的表示法是float,以及为什么转换为Double和BigDecimal时会出现尾部不精确。这与二进制表示转换有关吗?无论如何,下面是代码及其输出: // Float - 32b float

我试图在Java中学习更多关于浮点、双精度和大小数的知识。我想确切地知道浮点数在每种类型中是如何表示的,例如,浮点数使用2^,大小数使用10^加上刻度(32位)和无刻度值(任意精度)

我用这三种类型组合了简单的计算,并对每种类型进行了对话,结果相当混乱。我希望得到一些提示,说明为什么唯一正确的表示法是float,以及为什么转换为Double和BigDecimal时会出现尾部不精确。这与二进制表示转换有关吗?无论如何,下面是代码及其输出:

    // Float - 32b
    float a = 3.14f;
    float b = 3.100004f;
    float abAsAFloat = a + b;
    double abAsADouble = a + b;
    BigDecimal abAsABigDecimal = new BigDecimal(a + b);

    System.out.println("a + b as a float: " + abAsAFloat);
    System.out.println("a + b as a double: " + abAsADouble);
    System.out.println("a + b as a BigDecimal: " + abAsABigDecimal);

    // Double - 64b
    double c = 3.14;
    double d = 3.100004;

    double cdAsADouble = c + d;
    BigDecimal cdAsABigDecimal = new BigDecimal(c + d);

    System.out.println("c + d as a double: " + cdAsADouble);
    System.out.println("c + d as a BigDecimal: " + cdAsABigDecimal);

    // BigDecimal, arbitrary-precision, signBit*unscaledValue × 10^-scale
    BigDecimal e = new BigDecimal(3.14);
    BigDecimal f = new BigDecimal(3.100004);

    BigDecimal efAsABigDecimal = e.add(f);

    System.out.println("e + f: " + efAsABigDecimal);

    // Drawbacks. speed, memory, native value equality, no overloads for +/- et al
a+b作为浮点数:6.240004

a+b双精度:6.240004062652588

a+b作为大十进制:6.240004062652587890625

双精度c+d:6.24000400000001

c+d作为一个大十进制: 6.24000400000000772274688642976900196075439453125

e+f:6.24000400000000328185478792875073850154876708984375


float
对于这种特殊情况可能看起来是正确的,但对于其他值来说也是错误的。请注意,当
float
double
转换为字符串时,仅打印获得该类型中正确值所需的位数;这意味着
float
可以打印“正确答案”,即使该表示法隐藏的舍入误差与
double
一样大

BigDecimal
的问题在于您没有正确地使用它:您应该编写
新的BigDecimal(“3.14”)
而不是
新的BigDecimal(3.14)
,这使得
double
能够在
BigDecimal
有机会“修复”之前“搞糟”


对于表示的详细信息,我们用有用的图表进行了详尽的解释,但简短的解释是,
float
double
将数字表示为+/-1*1。*2^,其中
float
存储22位尾数和8位指数,
double
分别使用52位和11位。

float
对于这种特殊情况可能看起来正确,但对于其他值也一样错误。请注意,当
float
double
转换为字符串时,仅打印获得该类型中正确值所需的位数;这意味着
float
可以打印“正确答案”,即使该表示法隐藏的舍入误差与
double
一样大

BigDecimal
的问题在于您没有正确地使用它:您应该编写
新的BigDecimal(“3.14”)
而不是
新的BigDecimal(3.14)
,这使得
double
能够在
BigDecimal
有机会“修复”之前“搞糟”


对于表示的详细信息,我们用有用的图表进行了详尽的解释,但简短的解释是,
float
double
将数字表示为+/-1*1。*2^,其中
float
存储22位尾数和8位指数,
double
分别使用52位和11位。

您无意中混合了类型。例如:

BigDecimal e = new BigDecimal(3.14);
BigDecimal f = new BigDecimal(3.100004);
在本例中,您提供了双倍作为输入,因此e和f将具有双余数。相反,请使用以下命令:

BigDecimal e = new BigDecimal("3.14");
BigDecimal f = new BigDecimal("3.100004");

浮点输出似乎是最精确的,因为Java“知道”浮点的精度有限,所以它不会打印15位数字。

您无意中混合了类型。例如:

BigDecimal e = new BigDecimal(3.14);
BigDecimal f = new BigDecimal(3.100004);
在本例中,您提供了双倍作为输入,因此e和f将具有双余数。相反,请使用以下命令:

BigDecimal e = new BigDecimal("3.14");
BigDecimal f = new BigDecimal("3.100004");

浮点输出似乎是最精确的,因为Java“知道”浮点的精度有限,所以它不会打印15位数字。

当您转换为
double
BigDecimal
时,它会转换为最接近的可表示值。当您转换为BigDecimal时,实际上是先转换为
double
,因为没有从
float
直接转换


通常,您希望使用
BigDecimal.valueOf(double)从
double
转换为BigDecimal
此方法假定一定程度的舍入,以匹配打印时的双精度值。

当您转换为
double
BigDecimal
时,它将转换为最接近的可表示值。当您转换为BigDecimal时,实际上是先转换为
double
,因为没有从
float
直接转换

通常,您希望使用
BigDecimal将
double
转换为BigDecimal。valueOf(double)
此方法假定一定程度的舍入,以匹配打印时的双精度值。请阅读以下内容:

特别是,5.6。数字促销

i、 e

在这种情况下,首先将a添加到b中,给出一个
float
结果,然后
float
将转换为
double
,并进行赋值。因此,与
(double)a+b
相比,它可能会失去精度

同样,当使用sum result作为构造函数的参数时

new BigDecimal(a + b)
首先,将
float a
添加到
float b
,给出一个
float
结果,然后将其转换为double,然后开始构造BigDecimal对象

除非您在末尾指定了
f
,否则任何带小数点的数值常量都被视为
双精度
,因此,将常量传递给构造函数时:

新的BigDecimal(3.100004)

数字存储为
double
,并作为
double
精度传递给构造函数。要获得更高的精度,请改用
String
参数构造函数:

新的BigDecimal(“3.100004”)

读一下:

特别是,5.6。数字促销