Why does +e canceled and -e not? - java

System.out.println(2e+5);
Above line's output is,
200000.0
While below line's,
System.out.println(2e-5);
output is,
2.0e-5
Why does 2e-5 is not solved down with -10^5 giving the output,
0.00002

Because that's how the designers of the Double class chose to implement it:
[...]
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." [...]
They could have made another choice, of course, but that's simply how it is.
As the documentation says, if you want a specific format, use a NumberFormat to format your double.

As already pointed out by #Nizet, when converting double to string, the output will have scientific notation if number of digits are large. And this is not just for decimals.
Consider:
double d = 1500000000;
System.out.println(String.valueOf(d));
This will print 1.5E9
If you want conversion to happen in readable format, use String.format
System.out.println(String.format ("%.0f", d));
will print 1500000000

Related

if 0.1 has no binary representation, why I get 0.1

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.

Numeric literals

I was reading a book about Java and I found the following points unclear, please help me:
For integer literal expressed in any base other than base 10 (0b, 0, 0x) can we use the L suffix that stands for Long?
For floating point can we use any other base other than decimal? If yes can we specify float or double using F or D for other bases other than 10?
If yes with other bases than 10 could we use scientific notation or only decimal point is allowed?
1) Yes, it's possible for hexadecimal, octal and binary too. See jls-3.10.1
2) Yes, you can use hexadecimal notation, but you are restricted to binary exponents and specifying the exponent is required. See jls-3.10.2
Examples:
0xFF.Ap0d
0xFF.1p0f
0xFF.Ap1d
0xFF.Ap-1f
0xFF.Ap-1
0x.1p16
If you print these literals using System.out.println, you get:
255.625
255.0625
511.25
127.8125
63.90625
4096.0
The meaning of the binary exponent is as follows:
The value in front of the p or P is multipled by 2^z where z is the integer after the p (or P). The integer is in decimal format. E.g. 0xFF.1Ap0101d stands for 255.1015625 * 2^101.

setting decimal places to a float value

float a= (float) 1846.4;
NumberFormat df = DecimalFormat.getInstance();
df.setMinimumFractionDigits(2);
df.setMaximumFractionDigits(2);
float b = Float.parseFloat( df.format(a));
What would be the best way to set decimal places for a float (I just want to set 2 decimal places of a float value which can be 2013.43452 or 2392.2) ? Now I am getting exception like Exception in thread "main" java.lang.NumberFormatException: For input string: "1,846.40".
I think the direct problem causing the NFE is the thousand separators in the string, not the number of decimal places. You have both a ',' and a '.' in the string, and parseFloat doesn't like that.
Note, however, that you can't fix the number of decimal places in a float value - it is entirely a formatting issue. Specifically, trailing 0's have no significance in floating point values, thus will not be shown by default. You need to format the value according to your wishes at the point of output (when converting it into a displayable String e.g. by using DecimalFormat as you did above).
To get your formatting + parsing to work, just use df again:
float b = df.parse( df.format(a));
However, I still don't see any sense in that. You can't define the number of decimal places in a floating point number. 1846.40 is the same as 1846.4 or 1846.400, the trailing zeros are totally irrelevant.
Those digits come into play when you have output, e.g. writing the number to a string. But there are other facilities to do that, e.g. a string format pattern.
If you need to restrict the number of fraction digits internally use BigDecimal where you can set the scale and thus define the number of fraction digits it represents.
Sounds like you simply want to round to two decimal places.
Number format and mucking around with strings isn't where you want to go.
Try this:
float b = Math.round(a * 100)/100.0f;
What would be the best way to set decimal places for a float
There isn't one. Floats don't have decimal places. They have binary places.
If you want decimal places you have to use a decimal radix, either a BigDecimal or the result of DecimalFormat.format().

Java division for double and float without E

I'm doing some large number divisions (long/long to double, and int/int to float).. But I bump, to a problem when the results include the "E". I know we can use NumberFormat to format when displaying, but that's not what I. Just want the result of the divisions to not involve the "E", i.e. just round it up to the closest float/double that fits in the space.
Anybody got an idea?
The internal representation of floating point number does not have a switch for E presence or not (check IEEE-754). So your float/double number is just number (not a number with E or without it).
The only place where you get E is when you print this value out. And while Java uses number formater for printing, so I don't see a point why you don't want to use it here.
System.out.println(new DecimalFormat("#.#####").format(doubleValue));
The general problem that double and float in binary format. It not always possible to convert decimal fraction to binary fraction. For example 0.2 decmal fraction have infinitely many digits in binary (double) format. So whe converted from bynary format to decimal string, it result something like "0.2000000001" what displayed with E. To solve this problem you can use BigDecimal class what contains number in decimal format, so no E problem - it can easy rounded to any decimal point by setScale method. Or you can sore double as is, an write it to output by String.format("My value are: %.3f", value) - i recommend this way.
If you just want round you value to decimal point you can use:
new BigDecimal(val).setScale(3, RoundingMode.HALF_EVEN).doubleValue()
But there no any garanty what this core return double with fine fraction numbers.

How to read a double value with a certain precision

How to read a double value from a String with a certain precision (say 4) assuming the string contains something like "10.1234" using this api
If you want decimal precision, double is the wrong target type, as it is a binary format that cannot accurately represent most round decimal fractions. That double value will actually be rounded to something like 10.123399999999999999976
Instead, use BigDecimal all the way, or forget about runding while you read and manipulate the data, and round it only when you print the result.
Read The Floating-Point Guide for more information.
System.out.println(new Double(new BigDecimal("10.123456789").
setScale(4, BigDecimal.ROUND_DOWN). // choose precision and specify rounding policy
doubleValue()
));
>> run:
10.1234
I assume that your String also contains letters.
You can parse the number out of the String first:
String numberString = ...
int precision = ...
int index = numberString.indexOf(".");
numberString = numberString.substring(0, index+precision+1); // Maybe without "+1"
Double number = Double.valueOf(numberString);
You can use regular expression to truncate the String to at most 4 digits following the decimal point, then use Double.valueOf.
String[] tests = {
"12",
"12.",
"12.3",
"12.34",
"12.345",
"12.3456",
"12.34567",
"-123.45678",
"1.23456.789.0",
};
for (String test : tests) {
String truncated = test.replaceAll("(\\.\\d{4}).*", "$1");
System.out.printf("%15s %15s %15s%n",
test, truncated, Double.valueOf(truncated)
);
}
This prints:
12 12 12.0
12. 12. 12.0
12.3 12.3 12.3
12.34 12.34 12.34
12.345 12.345 12.345
12.3456 12.3456 12.3456
12.34567 12.3456 12.3456
-123.45678 -123.4567 -123.4567
1.23456.789.0 1.2345 1.2345
How the regex works
It captures a literal ., followed by up to four digits \d{4}, into \1. It also matches everything else that may follow .*, and replaces the whole thing with $1 (backreference to what \1 captured).
The advantage of this over, say, a simple indexOf approach is that it works even when there aren't 4 digits, or even when there isn't even a decimal point at all, without requiring special treatment.
See also
regular-expressions.info
Java Tutorials/Regular expressions
You can do something like
Math.round(number*100)/100
to get the precision, but this will probably not do what you want due to the internal representation of floats and doubles.
If you really need to work with a fixed number of digits after the decimal point consider using BigDecimal.
For formatting output you can use the C-like printf functionality as decribed in this article. It is not pretty but practical.

Categories

Resources