Double manipulation trouble - java

Suppose n is a Double type variable .
double right=n-(Math.ceil(n)-1);
//Here I am trying to get the right part of the number.
Now if n=1234.78
then right=0.7799999999999727
why not .78?
and when
n=1234.89
then right=0.8900000000001
why not 89? and why not 9999... here instead of 000000....?
Now suppose I want to find the sum of digits in right..Like in my example for 1234.89 its 8+9=17 or 1234.781 its 7+8+1-16. So then ?what should I do?
But I can't do it using floating point arithmatic?Like
double temp=0.0;
while(right>0)
{
right=rigth*10;
temp=Math.floor(right);
right=right-temp;
suml+=temp;
}
in kind of a way I mentioned above?
I am new to java. please explain my problem. It would be a great help for me. Thank you.

Hey you can use the following code
double roundTwoDecimals(double d) {
DecimalFormat twoDForm = new DecimalFormat("#.##");
return Double.valueOf(twoDForm.format(d));
}
right=roundTwoDecimals(right);
System.out.println(right);
You will get desired result.

floating point works the same in almost all languages and you see the same issues. If you want the fractional part you should use.
double fract = n - (long) n;
I suspect the formula you are using will not work for negative numbers. (and is slower)
This can produce a rounding error as you have seen so you need to chose a level of precision. You might choose 2 or 6 digits. You can round the value when you calculate it but it's often simpler to round it when you print it.
System.out.printf("%.2f%n", fract);
This will print 0.78 and 0.89 as you expect.

Related

Floats not adding up [duplicate]

I'm wondering what the best way to fix precision errors is in Java. As you can see in the following example, there are precision errors:
class FloatTest
{
public static void main(String[] args)
{
Float number1 = 1.89f;
for(int i = 11; i < 800; i*=2)
{
System.out.println("loop value: " + i);
System.out.println(i*number1);
System.out.println("");
}
}
}
The result displayed is:
loop value: 11
20.789999
loop value: 22
41.579998
loop value: 44
83.159996
loop value: 88
166.31999
loop value: 176
332.63998
loop value: 352
665.27997
loop value: 704
1330.5599
Also, if someone can explain why it only does it starting at 11 and doubling the value every time. I think all other values (or many of them at least) displayed the correct result.
Problems like this have caused me headache in the past and I usually use number formatters or put them into a String.
Edit: As people have mentioned, I could use a double, but after trying it, it seems that 1.89 as a double times 792 still outputs an error (the output is 1496.8799999999999).
I guess I'll try the other solutions such as BigDecimal
If you really care about precision, you should use BigDecimal
https://docs.oracle.com/javase/8/docs/api/java/math/BigDecimal.html
https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/math/BigDecimal.html
The problem is not with Java but with the good standard float's (http://en.wikipedia.org/wiki/IEEE_floating-point_standard).
You can either:
use Double and have a bit more precision (but not perfect of course, it also has limited precision)
use a arbitrary-precision-library
use numerically stable algorithms and truncate/round digits of which you are not sure they are correct (you can calculate numeric precision of operations)
When you print the result of a double operation you need to use appropriate rounding.
System.out.printf("%.2f%n", 1.89 * 792);
prints
1496.88
If you want to round the result to a precision, you can use rounding.
double d = 1.89 * 792;
d = Math.round(d * 100) / 100.0;
System.out.println(d);
prints
1496.88
However if you see below, this prints as expected, as there is a small amount of implied rounding.
It worth nothing that (double) 1.89 is not exactly 1.89 It is a close approximation.
new BigDecimal(double) converts the exact value of double without any implied rounding. It can be useful in finding the exact value of a double.
System.out.println(new BigDecimal(1.89));
System.out.println(new BigDecimal(1496.88));
prints
1.8899999999999999023003738329862244427204132080078125
1496.8800000000001091393642127513885498046875
Most of your question has been pretty well covered, though you might still benefit from reading the [floating-point] tag wiki to understand why the other answers work.
However, nobody has addressed "why it only does it starting at 11 and doubling the value every time," so here's the answer to that:
for(int i = 11; i < 800; i*=2)
╚═══╤════╝ ╚╤═╝
│ └───── "double the value every time"
│
└───── "start at 11"
You could use doubles instead of floats
If you really need arbitrary precision, use BigDecimal.
first of Float is the wrapper class for the primitive float
and doubles have more precision
but if you only want to calculate down to the second digit (for monetary purposes for example) use an integer (as if you are using cents as unit) and add some scaling logic when you are multiplying/dividing
or if you need arbitrary precision use BigDecimal
If precision is vital, you should use BigDecimal to make sure that the required precision remains. When you instantiate the calculation, remember to use strings to instantiate the values instead of doubles.
I never had a problem with simple arithmetic precision in either Basic, Visual Basic, FORTRAN, ALGOL or other "primitive" languages. It is beyond comprehension that JAVA can't do simple arithmetic without introducing errors. I need just two digits to the right of the decimal point for doing some accounting. Using Float subtracting 1000 from 1355.65 I get 355.650002! In order to get around this ridiculous error I have implemented a simple solution. I process my input by separating the values on each side of the decimal point as character, convert each to integers, multiply each by 1000 and add the two back together as integers. Ridiculous but there are no errors introduced by the poor JAVA algorithms.

Doing double - int in java

For example if I do this:
double decPart = 5.57 - 5;
System.out.println(decPart);
it returns 0.5700000000000003, instead of just 0.57. I can print it out properly using System.out.printf("%.2f", decPart), but that doesn't solve the problem (Note: the decimal part is not necessarily 2 decimal places). So for example if I try to do this:
System.out.println(1.0 - decPart);
it would return 0.4299999999999997
Can somebody please explain this behavior and how to fix it. Thanks in advance.
This is due to floating point imprecision. Floating-point numbers (float, double in Java) cannot represent some numbers exactly. If you're looking for absolute precision, look into BigDecimal.

Trying to multiply double by int in java

I am trying to multiply 1207.87 by 10000 and expecting 12078700.0 but I am getting 1.2078699999999998E7
I understand that its related to precision mistake but how do i rectify this problem
EDIT:-
I simply want to remove the decimal
try this:
1207.87f * 10000
the result will be:
1.20787E7
This is because of float numbers representation.
You can:
round it Math.round(...)
or use BigDecimal if you need high precision.
More about What Every Computer Scientist Should Know About Floating-Point Arithmetic.
You need to do the CAST:
(int) 1207.87 * 10000
You cannot rectify this if you use double type. You can if you use BigDecimal.
Try to use decimal format like:
DecimalFormat f = new DecimalFormat("#0.00");
f.format(Double.valueOf(yourDouble));
Hope this can help you!
You can use formatted output as below:
double ans = 1207.87 * 10000;
System.out.printf("ans: %.0f\n", ans);
Output:
ans: 12078700
double are stored in exponental precision in java and many other languages. see IEEE754for more information about float, double and their variant
If you want a integer result, then cast your floating point number, or the result. If you want to just print a floating number in "ordinary notation", then you can use the class NumberFormat
NumberFormat formatter = new DecimalFormat("#0.00");
System.out.println(formatter.format(4.0));
example taken from here
finally you can use a fixed precision number with the class BigDecimal, but please take care that this is normally not hardware (FPU) accelerated so will slow down a lot your calculation, but will give you fixed error. That kind of number is especially used in simulation where error must be know
Simple way would be this one:
Double j = 1207.87;
int x = j.intValue();
System.out.println(x * 10000);

Weird decimal calculation in Java, potentially a bug?

I have weird decimal calculation that really surprise me, I have two big decimal number, one is a normal proce and the other one is an offer price. Then I want to calculate discount percentage and ceil it to the nearest integer.
Here are the code:
BigDecimal listPrice = new BigDecimal(510000);
BigDecimal offerPrice = new BigDecimal(433500);
int itemDiscount = (int)Math.ceil(((listPrice.longValue() - offerPrice.longValue()) / (float) listPrice.longValue()) * 100);
I expect it would set 15 as value of itemDiscount, but surprisingly it has 16, wow. Then i print each calculation to show in which statement is the problem, so i put System.out.println for each statement as below :
System.out.println(listPrice.longValue() - offerPrice.longValue()); //==> show 76500
System.out.println((listPrice.longValue() - offerPrice.longValue()) / (float) listPrice.longValue()); // ==> 0.15
System.out.println((listPrice.longValue() - offerPrice.longValue()) * 100 / (float) listPrice.longValue()); // ==> 15.000001
the problem is in above statement, istead of returning 15.0, it return 15.000001. And when i ceil it, it will of course return 16 instead of 15.
What is the explanation if this case? is this the way it is or it is a bug?
What is the explanation if this case? is this the way it is or it is a bug?
It is the way it is. It is not a bug.
You are doing the calculation using floating point types (float) and floating point arithmetic is imprecise.
I'm not sure what the best fix is here. Maybe doing the computation using BigDecimal arithmetic methods would give a better result, but it is by no means guaranteed that you won't get similar problems in this calculation with different inputs ...
However, I suspect that the real problem is that you should not be using ceil in that calculation. Even BigDecimal will give you rounding errors; e.g. if your computation involves dividing by 3, the intermediate result cannot be precisely represented using a base-10 representation.
The correct way to do calculations using Real numbers is to properly take account of the error bars in the calculation.
Try using the divide method directly from the BigDecimal class. If you are casting to a float then you are not using the benefit of BigDecimal .
http://www.roseindia.net/java/java-bigdecimal/bigDecimal-divide-int.shtml

Java Math.pow() Rounding Error

I'm having trouble with (what I suspect is) a rounding error.
I have a string, 0.686357E-01, which I'm trying to convert to a double. I've been able to split it up using the Pattern.split() function, and I'm capturing the base and the exponent values just fine. However, once I try to multiply them appropriately, I get this as a result: 0.06863570000000001.
Here's my relevant code:
pattern = Pattern.compile("E\\+?");
String[] number = pattern.split(string);
double base = Double.parseDouble(number[0]);
int exponent = Integer.parseInt(number[1]);
number= base*Math.pow(10, exponent);
So, how do I avoid the rounding error? (There are ways that I can work around it, but if it's possible to do, then I'd like to know how to fix the issue)
Thanks.
You don't need to split it, Double.parseDouble can handle those kinds of numbers just fine.
double number = Double.parseDouble("0.686357E-01");
See? It works!
0.0686357 is not exactly representable as a double-precision value.
Two solutions:
Use e.g. BigDecimal.
Limit the displayed precision to a certain number of significant figures when converting back to human-readable.
Floating point numbers do not have perfect precision. If that is an issue, use BigDecimal:
String string = "0.686357E-01";
BigDecimal number = new BigDecimal(string);
System.out.println(number);
Double will print always like that, but the value will remain correct. You'll need to format the output to get the correct value. See DecimalFormat class.

Categories

Resources