I want to know how to get hexadecimal representation of float number.
I tried following code
System.out.println(Float.toHexString(56));
Got o/p
0x1.cp5
I really do not understand. If I use Integer method the o/p would be 38, which I can understand...but how o/p comes 0x1.cp5. Could any one tell me or point to some good tutorial..thanks in advance.
Just refer to java.lang.Float javadocs:
http://docs.oracle.com/javase/7/docs/api/java/lang/Float.html#toHexString%28float%29
If m is a float value with a normalized representation, substrings are used to represent the significand and exponent fields. The
significand is represented by the characters "0x1." followed by a
lowercase hexadecimal representation of the rest of the significand as
a fraction. Trailing zeros in the hexadecimal representation are
removed unless all the digits are zero, in which case a single zero is
used. Next, the exponent is represented by "p" followed by a decimal
string of the unbiased exponent as if produced by a call to
Integer.toString on the exponent value.
If m is a float value with a subnormal representation, the significand is represented by the characters "0x0." followed by a
hexadecimal representation of the rest of the significand as a
fraction. Trailing zeros in the hexadecimal representation are
removed. Next, the exponent is represented by "p-126". Note that there
must be at least one nonzero digit in a subnormal significand.
Use this tool to see what happens to your float when represented in IEEE 754 format.
56 in binary is 111000 which when normalized converts to 1.11000.
As the javadoc says, 0x1. is for the significand part, which is in this case '1100' in binary, which is 'c' in hex. And the exponent part is 5.
Related
When I run:
System.out.println(1f - 0.9f);
I get:
0.100000024
This is because 0.1 has no representation in binary.
Then why when I print this:
System.out.println(0.1f);
I get this:
0.1
0.1 can be represented better in floating point than 0.9. Loosely speaking that's because 0.1 is smaller and closer to its nearest dyadic rational.
So the error when subtracting from 1.0 is larger.
Hence the two values differ.
The embedded formatting heuristics in println do a better job with the 0.1
The value of 0.1f
Java’s float uses IEEE-754 basic 32-bit binary floating-point. In binary
floating-point, every representable number is an integer multiple of some
power of two. (This includes non-negative powers 1, 2, 4, 8, 16,…, and it
includes negative powers ½, ¼, ⅛, 1/16, 1/32,…)
For numbers from 1 to 2, the representable numbers are multiples of
2−23, which is 0.00000011920928955078125:
1.00000000000000000000000
1.00000011920928955078125
1.00000023841857910156250
1.00000035762786865234375
1.00000047683715820312500
…
For numbers near 0.1, the representable numbers are multiples of 2−27, which is 0.000000007450580596923828125:
…
0.099999979138374328613281250 (a)
0.099999986588954925537109375 (b)
0.099999994039535522460937500 (c)
0.100000001490116119384765625 (d)
0.100000008940696716308593750 (e)
0.100000016391277313232421875 (f)
…
(I labeled the numbers (a) to (f) to refer to them in text below.)
As we can see, the closest of these to 0.1 is (d), 0.100000001490116119384765625.
Thus, when 0.1 appears in source code, it is converted to this value,
0.100000001490116119384765625.
This is a general rule—any numeral in source code is converted to the nearest representable number.
(Note that 0.1 is not “represented by” 0.100000001490116119384765625, and
0.100000001490116119384765625 does not “represent” 0.1. The float
0.100000001490116119384765625 is exactly that. The 0.1f in source text was
converted to 0.100000001490116119384765625 and is now just that value.)
If 0.1f is not 0.1, why is “0.1” printed?
Java’s default formatting for floating-point numbers uses the fewest
significant decimal digits needed to distinguish the number from nearby
representable numbers.
The rule for Java SE 10 can be found in the documentation for java.lang.float, in
the toString(float d) section. I quote the passage below1. The
critical part says:
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 float. That is, suppose that x is the exact mathematical value represented by the decimal representation produced by this method for a finite nonzero argument f. Then f must be the float value nearest to x; or, if two float values are equally close to x, then f must be one of them and the least significant bit of the significand of f must be 0.
Let us see how this applies while formatting 0.100000001490116119384765625 and
0.099999994039535522460937500.
For 0.100000001490116119384765625, which is (d), we will first consider formatting one digit
after the decimal point: “0.1”. This represents the number 0.1, of course.
Now, we ask: Is this good enough? If we take 0.1 and ask which number in the
list of nearby numbers above is closest, what is the answer? The nearest number
in the list is (d), 0.100000001490116119384765625. That is the number we are
formatting, so we are done, and the result is “0.1”. This does not mean the float is 0.1, just that, when it is converted to a string with default options, the result is the string “0.1”.
Now consider 0.099999994039535522460937500, which is (c). Again, if we consider using just
one digit, the number rounds to 0.1. When we ask which number in the list is
closest to that, the answer is (d), 0.100000001490116119384765625. That is not the
number we are formatting, so we need more digits. If we consider two digits,
rounding would give us 0.10, and that clearly is also not enough. Considering
more and more digits gives us 0.100, 0.1000, and so on, until we get to eight
digits. With eight digits, 0.099999994039535522460937500 rounds to
0.09999999. Now, when we check the list, we see the nearest number is
(b), 0.099999986588954925537109375. (Adding about 0.0000000035 to that produces
0.09999999, whereas the number we are formatting is about 0.0000000040 away,
which is farther.) So we try nine digits, which gives us 0.099999994. Finally,
the closest number in the list is (c), 0.099999994039535522460937500, which is the
number we are formatting, so we are done, and the result is “0.099999994”.
Footnote
1 The documentation for toString(float d) says:
Returns a string representation of the float argument. All characters mentioned below are ASCII characters.
If the argument is NaN, the result is the string "NaN".
Otherwise, the result is a string that represents the sign and magnitude (absolute value) of the argument. If the sign is negative, the first character of the result is '-' ('\u002D'); if the sign is positive, no sign character appears in the result. As for the magnitude m:
If m is infinity, it is represented by the characters "Infinity"; thus, positive infinity produces the result "Infinity" and negative infinity produces the result "-Infinity".
If m is zero, it is represented by the characters "0.0"; thus, negative zero produces the result "-0.0" and positive zero produces the result "0.0".
If m is greater than or equal to 10-3 but less than 107, then it is represented as the integer part of m, in decimal form with no leading zeroes, followed by '.' ('\u002E'), followed by one or more decimal digits representing the fractional part of m.
If m is less than 10-3 or greater than or equal to 107, then it is represented in so-called "computerized scientific notation." Let n be the unique integer such that 10n ≤ m < 10n+1; then let a be the mathematically exact quotient of m and 10n so that 1 ≤ a < 10. The magnitude is then represented as the integer part of a, as a single decimal digit, followed by '.' ('\u002E'), followed by decimal digits representing the fractional part of a, followed by the letter 'E' ('\u0045'), followed by a representation of n as a decimal integer, as produced by the method Integer.toString(int).
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 float. That is, suppose that x is the exact mathematical value represented by the decimal representation produced by this method for a finite nonzero argument f. Then f must be the float value nearest to x; or, if two float values are equally close to x, then f must be one of them and the least significant bit of the significand of f must be 0.
System.out.println, and most methods of converting floating-point numbers to strings, operate using the following rule: they use exactly as many digits are necessary so that the true value of the double is the closest representable number to the printed value.
That is, it only prints out the digits 0.1 because the true value of the double, 0.1000000000000000055511151231257827021181583404541015625, is the closest double to the displayed value.
I'm working on a method that translates a string into an appropriate Number type, depending upon the format of the number. If the number appears to be a floating point value, then I need to return the smallest type I can use without sacrificing precision (Float, Double or BigDecimal).
Based on How many significant digits have floats and doubles in java? (and other resources), I've learned than Float values have 23 bits for the mantissa. Based on this, I used the following method to return the bit length for a given value:
private static int getBitLengthOfSignificand(String integerPart,
String fractionalPart) {
return new BigInteger(integerPart + fractionalPart).bitLength();
}
If the result of this test is below 24, I return a Float. If below 53 I return a Double, otherwise a BigDecimal.
However, I'm confused by the result when I consider Float.MAX_VALUE, which is 3.4028235E38. The bit length of the significand is 26 according to my method (where integerPart = 3 and fractionalPart = 4028235. This triggers my method to return a Double, when clearly Float would suffice.
Can someone highlight the flaw in my thinking or implementation? Another idea I had was to convert the string to a BigDecimal and scale down using floatValue() and doubleValue(), testing for overflow (which is represented by infinite values). But that loses precision, so isn't appropriate for me.
The significand is stored in binary, and you can think of it as a number in its decimal representation only if you don't let it confuse you.
The exponent is a binary exponent that does not represent a multiplication by a power of ten but by a power of two. For this reason, the E38 in the number you used as example is only a convenience: the real significand is in binary and should be multiplied by a power of two to obtain the actual number. Powers of two and powers of ten aren't the same, so “3.4028235” is not the real significand.
The real significand of Float.MAX_VALUE is in hexadecimal notation, 0x1.fffffe, and its associated exponent is 127, meaning that Float.MAX_VALUE is actually 0x1.fffffe * 2127.
Looking at the decimal representation to choose a binary floating-point type to put the value in, as you are trying to do, doesn't work. For one thing, the number of decimal digits that one is sure to recover from a float is different from the number of decimal digits one may need to write to distinguish a float from its neighbors (6 and 9 respectively). You chose to write “3.4028235E38” but you could have written 3.40282E38, which for your algorithm, looks easier to represent, when it isn't, really. When people write that “3.4028235E38” is the largest finite value of the float type, they mean that if you round this decimal number to float, you will arrive to the largest float. If you parse “3.4028235E38” as a double-precision number it won't even be equal to Float.MAX_VALUE.
To put it differently: another way to write Float.MAX_VALUE is 3.4028234663852885981170418348451692544E38. It is still representable as a float (it represents the exact same value as 3.4028235E38). It looks like it has many digits because these are decimal digits that appear for a decimal exponent, when in fact the number is represented internally with a binary exponent.
(By the way, your approach does not check that the exponent is in range to represent a number in the chosen type, which is another condition for a type to be able to represent the number from a string.)
I would work in terms of the difference between the actual value and the nearest float. BigDecimal can store any finite length decimal fraction exactly and do arithmetic on it:
Convert the String to the nearest float x. If x is infinite, but the value has a finite double representation use that.
Convert the String exactly to BigDecimal y.
If y is zero, use float, which can represent zero exactly.
If not, convert the float x to BigDecimal, z.
Calculate, in BigDecimal to a reasonable number of decimal places, the absolute value of (y-z)/z. That is the relative rounding error due to using float. If it is small enough for your purposes, less than some value you pick, use float. If not, use double.
If you literally want no sacrifice in precision, it is much simpler. Convert to both float and double. Compare them for equality. The comparison will be done in double. If they compare equal, go with the float. If not, go with the double.
I am just wonder how to use bit operations to achieve the goal: given an IEEE binary representation of a real, for example, 40AC0000 (5.375 in decimal), how to get its true binary representation (expecting 101.011 for the example) in Java?
This is kind of a tough question, especially if you don't already know about IEEE floats.
Since there are 4 bytes in your number, it's single precision. This means it has a structure of 1 sign bit, 8 Exponent bits and 23 Mantissa bits. The sign bit is obvious. The meaning of the exponent bits affects how you interpret the Mantissa bits. First check the 8 exponents bits. If they are all 0, you have a denormalized number; if they are all 1, you have an infinity value or a NaN; otherwise, it is normalized.
In the normalized , take the exponent bits, interpret it as an 8 bit number and subtract 127_10 (or 0xf7) from it. This is your exponent. Then take the remaining Mantissa bits, add a leading 1. Your result is then (-1)^[Sign] * 1.[Mantissa] * 2^[Exponent].
If it is a denormalized number, your exponent is -126 (1-127). In this case, interpret as (-1)^[Sign] * 0.[Mantissa] * 2^[Exponent].
In the remaining cases, if the Mantissa is all 0s, your number is (-1)^[Sign] * infinity. Otherwise, your float is a NaN.
Hope that helps.
Do you mean Float.floatToIntBits() and Float.intBitsToFloat() ?
What do you mean by "true binary representation"? There is nothing "untrue" about the hex representation (40AC0000).
You can convert between different radixes (hex, binary, decimal) using the methods on Integer:
Float.floatToIntBits(new Float("5.375"));
// = 1085014016
Integer.toString(1085014016, 16);
// = "40ac0000"
Integer.valueOf("40AC0000", 16);
// = 1085014016
Integer.toString(1085014016, 2);
// returns 1000000101011000000000000000000
I want to check the exponent of numbers generated in my program. (They are generated like 2.333E-4 , when I print). I want to check which numbers are having Exponent smaller than E-4, which needs to be increased by multiplying with 10 till they reach E-4.
Any ideas how to achieve this? Even if someone can tell me how to extract the exponent , it will be helpful.
You can use Java docs: Double.doubleToRawLongBits
Double.doubleToRawLongBits
public static long doubleToRawLongBits(double value)
Returns a representation of the specified floating-point value according to the IEEE 754 floating-point "double format" bit layout, preserving Not-a-Number (NaN) values.
Bit 63 (the bit that is selected by the mask 0x8000000000000000L) represents the sign of the floating-point number.
Bits 62-52 (the bits that are selected by the mask 0x7ff0000000000000L) represent the exponent.
Bits 51-0 (the bits that are selected by the mask 0x000fffffffffffffL) represent the significand (sometimes called the mantissa) of the floating-point number.
So you could get the double value into a long, shift by 13*4 (13 hex digits = 13*4 bits) to the right and check the exponent value that way.
This link will help with the decoding: IEEE754 double FP format - exponent encoding
Another way to extract the exponent is to use the logarithm (base 10) function (Math.log10(double a) in Java).
For the input value you give, it will return -3.6320852612062473. For the input value 1e-4, it will return -4. Therefore, here is what you could do (assuming that "number" is the double value you want to test in the code below):
while (Math.log10(number) < -4) {
number = number * 10;
}
You can do this
double d = 0.01234e-4;
if (d < 1e-4)
System.out.printf("%fE-4", d * 1e4);
else
System.out.printf("%g", d);
prints
0.012340E-4
Why does 0x1p3 equal 8.0? Why does 0x1e3 equal 483, whereas 0x1e3d equals 7741? It is confusing since 1e3d equals 1000.0.
0x1e3 and 0x1e3d are hexadecimal integer literals. Note that e and d are hexadecimal digits, not the exponent indicator or double type indicator in this case.
1e3d is a decimal floating-point literal. The e is the exponent indicator, the d says that this is a double rather than a float.
The notation 0x1p3 is a way to express a floating-point literal in hexadecimal, as you can read in section 3.10.2 of the Java Language Specification. It means 1 times 2 to the power 3; the exponent is binary (so, it's 2-to-the-power instead of 10-to-the-power).
0x1e3 is hex for 483, as is 0x1e3d hex for 7741. The e is being read as a hex digit with value 14.