Java Double.toString是否总是生成与Double literal完全相同的结果?
Java Double.toString是否总是生成与Double literal完全相同的结果?,java,floating-point,Java,Floating Point,Double.toString(0.1)生成“0.1”,但0.1是一个浮点数 浮点数在程序语言中不能精确表示,但Double.toString会产生精确的结果(0.1),它是如何做到的,它总是产生数学上等于双文本的结果吗 假设文字是双精度的 以下是我看到的问题: 当使用Apache POI读取excel文件时,XSSFCell.getNumericCellValue只能返回double,如果我使用BigDecimal.valueOf将其转换为BigDecimal,这总是安全的吗?为什么?10e-
Double.toString(0.1)
生成“0.1”,但0.1是一个浮点数
浮点数在程序语言中不能精确表示,但Double.toString会产生精确的结果(0.1),它是如何做到的,它总是产生数学上等于双文本的结果吗
假设文字是双精度的
以下是我看到的问题:
当使用Apache POI读取excel文件时,
XSSFCell.getNumericCellValue
只能返回double
,如果我使用BigDecimal.valueOf
将其转换为BigDecimal
,这总是安全的吗?为什么?10e-5d
是一个相当于10^-5的双字面值
Double.toString(10e-5d)
返回“1.0E-4”
嗯,Double
类型的精度有限,因此如果在浮点后添加足够的数字,其中一些数字将被截断/舍入
例如:
System.out.println (Double.toString(0.123456789123456789))
印刷品
0.12345678912345678
Double.toString产生精确的结果(0.1),它是如何做到的,它总是产生在数学上等于双文本的结果吗
Double。如果XXX
是具有15个或更少有效数字的十进制数字,并且在Double
格式的范围内,则toString(XXX)
将始终生成一个等于XXX
的数字
原因有两个:
Double
格式(IEEE-754 binary64)具有足够的精度,因此始终可以区分15位十进制数字Double.toString
不显示确切的Double
值,而是显示0.1
被转换为Double
值0.1000000000000005555115123125782702118158340451015625。但是默认情况下,Double.toString
不会生成所有这些数字。它使用的算法产生“0.1”,因为这足以将0.1000000000000005555115123125782702118158340451015625与其两个邻居(0.099999999999167332731531132594682276248931884765625和0.100000000000001942890293094023945741355419158935546875)唯一区分开来。这两个值都远离0.1
因此,Double.toString(1.234)
、Double.toString(123.4e-2)
、和Double.toString(.0001234e4)
都将产生“1.234”——一个数值等于所有原始十进制数字(在转换为Double
之前)的数字,尽管它在形式上与其中一些数字不同
当使用Apache POI读取excel文件时,XSSFCell.getNumericCellValue
只能返回double
,如果我使用BigDecimal.valueOf
将其转换为BigDecimal
,这是否总是安全的,为什么
如果要检索的单元格值不能表示为Double
,则XSSFCell.getNumericCellValue
必须更改它。从内存来看,我认为BigDecimal.valueOf
将生成返回的Double
的确切值,但我不能权威地对此进行说明。这是一个独立于Double
和Double.toString
行为的问题,因此您可以将其作为一个独立的问题提问。我同意,但另一种解释可能会有所帮助
对于每一个双精度数,都有一系列实数,根据半偶数规则进行四舍五入。对于0.10000000000000055115123125782702118158340451015625,四舍五入0.1到一个双精度的结果,范围是[0.09999999999861222219554324470460414886474609375,0.1000000000000012490009090907301079765626602178515625]
实数算术值在该范围内的任何双精度文字都具有与0.1相同的双精度值
Double.toString(x)
返回转换为x
且小数位数最少的范围内实数的字符串表示形式。选取该范围内的任何实数可确保使用double.toString将double转换为字符串,然后使用round-half-偶数规则将字符串转换回double的往返过程会恢复原始值
System.out.println(0.1000000000000005)
打印“0.1”,因为0.1000000000000005在四舍五入到与0.1相同的双精度范围内,0.1是该范围内小数位数最少的实数
这种效果很少可见,因为实数值在范围内的“0.1”以外的文字很少。由于精度较低,所以对于float更为明显<代码>系统输出打印项次(0.10000001F)打印“0.1”。
双精度。如果您真的这么问,toString(0.10)
将不会生成“0.10”
。您的意思是字符串如何精确打印0.1
,其中双精度的数字不精确0.1
@Eklavya是的。它是否总是为文字输入打印精确的结果?中的双精度值没有精确表示,但赋值后双精度值是精确的。有道理吗?@Eklavya双d=0.1
d
没有准确存储该值。如果使用new BigDecimal(0.1)
进行测试,则将其打印出来,结果为0.10000000000000055115123125782702118158340451015625
。谢谢您的回答。也许我的问题不清楚。如果数字是有限的,在双精度,并且不考虑尾随0。结果在数学上总是等于文字吗?@ss。你的问题没有提到限制数字。也许你应该修改你的问题,使之精确。如果要限制数字,必须指定限制。