why program can exactly display infinite repeating floating point number in java or other language

懵懂的女人 提交于 2019-12-13 07:51:16

问题


like a decimal number 0.1, represented as binary 0.00011001100110011...., this is a infinite repeating number. when I write code like this:

float f = 0.1f;

the program will rounding it as binary 0 01111011 1001 1001 1001 1001 1001 101, this is not original number 0.1. but when print this variable like this:

System.out.print(f);

I can get original number 0.1 rather than 0.100000001 or some other number. I think the program can't exactly represent "0.1", but it can display "0.1" exactly. How to do it?

I recover decimal number through add each bits of binary, it looks weird.

float f = (float) (Math.pow(2, -4) + Math.pow(2, -5) + Math.pow(2, -8) + Math.pow(2, -9) + Math.pow(2, -12) + Math.pow(2, -13) + Math.pow(2, -16) + Math.pow(2, -17) + Math.pow(2, -20) + Math.pow(2, -21) + Math.pow(2, -24) + Math.pow(2, -25));

float f2 = (float) Math.pow(2, -27);

System.out.println(f);

System.out.println(f2);

System.out.println(f + f2);

Output:

0.099999994

7.4505806E-9

0.1

in math, f1 + f2 = 0.100000001145... , not equals 0.1. Why the program would not get result like 0.100000001, I think it is more accurate.


回答1:


Java's System.out.print prints just enough decimals that the resulting representation, if parsed as a double or float, converts to the original double or float value.

This is a good idea because it means that in a sense, no information is lost in this kind of conversion to decimal. On the other hand, it can give an impression of exactness which, as you make clear in your question, is wrong.

In other languages, you can print the exact decimal representation of the float or double being considered:

#include <stdio.h>

int main(){
  printf("%.60f", 0.1);
}

result: 0.100000000000000005551115123125782702118158340454101562500000

In Java, in order to emulate the above behavior, you need to convert the float or double to BigDecimal (this conversion is exact) and then print the BigDecimal with enough digits. Java's attitude to floating-point-to-string-representing-a-decimal conversion is pervasive, so that even System.out.format is affected. The linked Java program, the important line of which is System.out.format("%.60f\n", 0.1);, shows 0.100000000000000000000000000000000000000000000000000000000000, although the value of 0.1d is not 0.10000000000000000000…, and a Java programmer could have been excused for expecting the same output as the C program.

To convert a double to a string that represents the exact value of the double, consider the hexadecimal format, that Java supports for literals and for printing.




回答2:


I believe this is covered by Double.toString(double) (and similarly in Float#toString(float)):

How many digits must be printed for the fractional part of m or a? There must be at least one digit to represent the fractional part, and beyond that as many, but only as many, more digits as are needed to uniquely distinguish the argument value from adjacent values of type double. That is, suppose that x is the exact mathematical value represented by the decimal representation produced by this method for a finite nonzero argument d. Then d must be the double value nearest to x; or if two double values are equally close to x, then d must be one of them and the least significant bit of the significand of d must be 0.

(my emphasis)



来源:https://stackoverflow.com/questions/28395232/why-program-can-exactly-display-infinite-repeating-floating-point-number-in-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!