Why does Math.cbrt(a) give a different result than Math.pow(a, (1/3))?
public class HelloWorld{
public static void main(String []args){
int a=8;
System.out.println(Math.cbrt(a));
System.out.println(Math.pow(a,(1/3)));
}
}
soln
2.0
1.0
why is there a discrepancy? Is my math wrong or syntax wrong or something that gotta do with pow?
System.out.println(Math.pow(a,(1.0/3.0)));
1/3 will be 0 thanks to integer arithmetic, so you either need to cast to a double, or simply use doubles as shown above, to get the desired result.
In Java 1/3 = 0, because you divide integer by integer. If you would use 1/3.0 your result in Math.pow would be fine.
The expression 1/3 is evaluated as an integer division, resulting in 0. Then, pow is called as pow(8, 0), which correctly returns 1. Try writing pow(a, (1.0 / 3.0)) instead.
One more thing you may take note of is, using cbrt() gives you the exact correct value for the expression whereas using pow() gives you an approximate value to it . You may ever try it by using a= 64, 125 , 216 or 343 for reference. This won't give you an exact round up value for pow() statement and in most case wrong value if you try to print the int value for the same by type-casting.
I hope this answer helps for better clarification.
Related
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.
I know the float and double is not accurate.I have a question like this.
double a=4.0/2.0;
System.out.println(a);
The output is 2.0. So whether the result is accurate or not.
The question comes from when I read the book Java Programming Language.
It shows me a method to set the scale of output like this.
System.out.println((int)(area*100)/100.0);
The statement set the output to two decimal places.And I know the floating-point arithmetic is not accurate.So can the statement always work?
In the first case, the result will be exactly 2.0. The reason is that 4.0 and 2.0 are both exactly representable as Java doubles. The divide operator returns the closest double to the real number division result, which is 2.0.
In the second case, whether you get an exact result or not will depend on the value of area. All exactly representable two decimal place doubles end in .00, .25, .50, or .75. The remaining two decimal place doubles can only be approximated.
The cast to int causes inaccuracies, and should be replaced by Math.round. The problem is that a positive double very slightly less than an integer casts to the next integer down, but rounds to the closest integer. Here is a program illustrating this issue:
import java.math.BigDecimal;
public class Test {
public static void main(String[] args) {
double area = 0.29;
System.out.println(new BigDecimal(area));
System.out.println(new BigDecimal(area*100));
System.out.println(new BigDecimal((int)(area*100)/100.0));
System.out.println((int)(area*100)/100.0);
System.out.println(Math.round(area*100)/100.0);
}
}
Output:
0.289999999999999980015985556747182272374629974365234375
28.999999999999996447286321199499070644378662109375
0.2800000000000000266453525910037569701671600341796875
0.28
0.29
The closest double to 0.29 is slightly smaller than it, and the result of multiplying by 100 is also very slightly less than 29. Casting to int gets 28, but rounding gets 29.
My question may seem simple, but still can not get something that works.
I need to customize the Math.round rounding format or something to make it work as follows:
If the number is 1.6 he should round to 1, if greater than or equal to 1.7 should round to 2.0 . And so to all other decimal results with # .6
The way I'm doing the 1.6 being rounded to 2 shall be rounded to 1.
How can I do that?
Thank you!
Simply do this:
double threshold = 0.7;
Math.round(x - threshold + 0.5);
You could write a method that takes a double variable as input and returns the integer based on the first digit after the point. For instance, you could convert the input to a String and delimit it at the decimal point. Then check if the first digit after the point is less or greater than 6.
Math.floor(x + 0.6);
It possibly may solve your question.
I have the following code:
int i = (int) 0.72;
System.out.println(i);
Which yields the following output:
0
I would of imagined that the variable i should have the value of 1 (since 0.72 > 0.5 => 1), why is this not the case?
(I imagine that when casting to int, it simply cuts of the decimal digits after the comma, not taking into account of rounding up; so I'll probably have to take care of that myself?)
Correct, casting to an int will just truncate the number. You can do something like this to get the result you are after:
int i = (int)Math.round(0.72);
System.out.println(i);
This will print 1 for 0.72 and 0 for 0.28 for example.
Because when you cast a double to int, decimal part is truncated
UPDATE Math.round will give your desired output instead of Math.ceil:
System.out.println(Math.round(0.72));
// will output 1
System.out.println(Math.round(0.20));
// will output 0
You can use Math.ceil :
System.out.println(Math.ceil(0.72));
// will output 1
System.out.println(Math.ceil(0.20));
// will output 1
Casting to an int implicity drops the decimal part. That's why you get 0 because anything after the 0 is removed (in your case the 72). If you want to round then look at Math.round(...)
Explicit cast does a conversion a float/double value to an int variable (which discards the fractional part)
Java does not round-off the number like we do.It simply truncates the decimal part.
If you want to round-off the number use java.lang.Math
Casting double to int truncates the non-integer portion of the number.
To round numbers as you describe, use Math.round()
As a complete Java beginner, and just in case my experience is useful to someone, I was just making the following mistake:
int x = (int) Math.random() * 10;
... which will always set x to 0. Instead, I should've done int x = (int) (Math.random() * 10);.
Not much of a Java-know-how specific mistake, but I'll just throw this in case anyone puzzled by this stumbles upon this question.
If you try to run the following code
public class Main {
public static void main(String[] args) {
long a = (long)Math.pow(13, 15);
System.out.println(a + " " + a%13);
}
}
You will get "51185893014090752 8"
The correct value of 13^15 is 51185893014090757, i.e. greater than the result returned by Math.pow by 5. Any ideas of what may cause it?
You've exceeded the number of significant digits available (~15 to 16) in double-precision floating-point values. Once you do that, you can't expect the least significant digit(s) of your result to actually be meaningful/precise.
If you need arbitrarily precise arithmetic in Java, consider using BigInteger and BigDecimal.
The problem is that as you get to higher and higher double values, the gap between consecutive values increases - a double can't represent every integer value within its range, and that's what's going wrong here. It's returning the closest double value to the exact result.
This is not a problem of precision. The Math.pow method performs an approximation of the result. To get the correct result use the following code.
long b = 13;
for(int i = 0; i != 14; i ++) {
b = b * 13;
}
System.out.println(b);
The output is the expected result 51185893014090757L.
More generally, the Math.pow method usage should be avoided when the exponent is an integer. First, the result is an approximation, and second it is more costly to compute.
The implementation of Math.pow (and most other methods in the Math class) is based on the network library netlib as the package "Freely Distributable Math Library" (see StrictMath javadoc). The implementation in C is available at e_pow.c.
A double has finite precision, its mantissa is 52 bits, which roughly equals 15 to 16 decimals. So the number you're trying to calculate can't be represented (exactly) by a double any more.
The correct answer is to provide the closest number which can be represented by a double
Have you checked whether this is the case or not?
it is because of the limit of holding digits in long by casting to double, float you may be able but it will have some errors, you should yourself handle the digits of the calculation by saving them in an array that's not an easy way
but in python programming language you can have the result of any length, it is so powerful!
be successful!!!