This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 1 year ago.
My task is to compare two numbers and return true if they are equal by three decimal places. When I print out the value of diff it is 0.0001, but it still doesn't enter the if(diff <= 0.0001) block.
public class DecimalComparator {
public static boolean areEqualByThreeDecimalPlaces(double num1, double num2) {
double diff = Math.abs(num1 - num2);
System.out.printf("%f", diff);
if(diff <= 0.0001) {
return true;
} else {
return false;
}
}
public static void main(String[] args) {
boolean test = areEqualByThreeDecimalPlaces(3.1756, 3.1755);
System.out.println(test);
test = areEqualByThreeDecimalPlaces(3.176, 3.175);
System.out.println(test);
}
}
When you need arbitrary precision use BigDecimal. Also, your magic number should be 0.001 for three decimal places. Like,
public static boolean areEqualByThreeDecimalPlaces(double num1, double num2) {
return new BigDecimal(num1).subtract(new BigDecimal(num2)).abs()
.compareTo(new BigDecimal(0.001)) <= 0;
}
public static void main(String[] args) {
System.out.println(areEqualByThreeDecimalPlaces(3.1756, 3.1755));
System.out.println(areEqualByThreeDecimalPlaces(3.176, 3.175));
}
Outputs
true
false
While I believe #Elliot Frisch has the best Java approach, it is always difficult to know if one should introduce concepts beyond the standard primitives for what appears to be homework.
In the alternative, knowing that the desired value is 3 decimal places, the problem may be re-conceptualized by multiplying by 1000 and using an int.
Example:
public static boolean areEqualByThreeDecimalPlaces(double num1, double num2) {
final int mult = 1000;
int i1 = (int)(num1 * mult);
int i2 = (int)(num2 * mult);
return (Math.abs(i1 - i2)) == 0;
}
The output shows the expected true and false for the test cases.
Just an alternative approach to consider if one cannot switch to using other Java classes.
Related
I try to use a recursive function to calculate the Euler number in Java. It's OK when I enter small numbers into this formula:
But when I try to enter a bigger number like 1000 I get infinity.
Why it's happening. How I can fix it.
import java.util.Scanner;
public class enumber {
public static long fact(int a) {
if(a <= 1) {
return 1;
}
return a * fact(a - 1);
}
public static double calculate(int i) {
double cresult = Math.pow(fact(i), -1);
if(i == 0 ) {
return 1;
}
return cresult+calculate(i-1);
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Enter i value: ");
int i = sc.nextInt();
double eresult = calculate(i);
System.out.println(eresult);
}
}
output;
Enter i value:
1000
Infinity
That's because you try to calculate the factorial of 1000....which is pretty huge.
Factorial 1000
You try to store it in a long value, but long's
max value is way smaller than 1000!. It basically doesn't fit anymore.
Consider using the class BigInteger (or BigDecimal), its in the default java sdk and you can directly output via println().
However you know the result already, its e, so you might only need to implement the Big-Class for the factorial.
You are exceeding the capacity of a long. But I would suggest you decide how much precision you want for e.
Let's say you want it to have an error of less than .0000001. Continue the iteration for e until the positive delta between your latest computation and the previous is less than or equal to your error.
If you want to take it to extremes, you can always use BigDecimal to increase the accuracy of your results.
I solved that problem by using loops. And for the old algorithm, I changed the fact method type to double. I get rid of Infinity. After that, I face "StackOverflowError".
What is a StackOverflowError?
My new algorithm is;
import java.util.Scanner;
public class enumber2 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
double fact;
double eNumber = 0;
int i = in.nextInt();
while(i>0) {
fact=1;
for(int j=1; j<=i; j++) {
fact = fact * j;
}
eNumber = eNumber +(1.0/fact);
i--;
}
eNumber = eNumber +1;
System.out.println(eNumber);
}
}
even I enter big numbers after a little bit of patient I'm getting results without exception.
This question already has answers here:
Int division: Why is the result of 1/3 == 0?
(19 answers)
Closed 2 years ago.
I have the following method in a Java program:
public void Div(int a, int b){
//exception in order to check if the second argument is 0
try{
int div1 = (a / b);
double div = div1;
System.out.println("The division of the two numbers is: " + div);
}
catch(ArithmeticException e){
System.out.println("You can't divide a number by 0");
}
This only works if numerator is larger than the denominator ( e.g 8/2). If the numerator is smaller than the denominator I get a result of 0.0 (e.g. 2/8).
What can I do to make it work?
It's happening because of integer division. You can cast one of the arguments to double and store the result to a double variable to fix the issue.
public class Main {
public static void main(String[] args) {
div(5, 10);
}
public static void div(int a, int b) {
try {
double div = (double) a / b;
System.out.println("The division of the two numbers is: " + div);
} catch (ArithmeticException e) {
System.out.println("You can't divide a number by 0");
}
}
}
Output:
The division of the two numbers is: 0.5
On a side note, you should follow Java naming conventions e.g. the method name, Div should be div as per the Java naming conventions.
(a/b) You're doing integer division. You need to typecast to other data types that can store decimal like double.
double div = (double) a / b;
This question already has answers here:
How to avoid floating point precision errors with floats or doubles in Java?
(12 answers)
Closed 5 years ago.
I have the following code.
public class ToBeDeleted {
public static final float MAX_PHYSICAL_LENGTH = 100000000;
public static void main(String[] args) {
//100000000
float temp = 100000000 -4;
System.out.println(temp);
if (MAX_PHYSICAL_LENGTH == temp)
System.out.println("True statement");
else
System.out.println("False Statement");
}
}
The output of the above is
1.0E8
True statement
Now with the below code
public class ToBeDeleted {
public static final float MAX_PHYSICAL_LENGTH = 100000000;
public static void main(String[] args) {
//100000000
float temp = 100000000 -5;
System.out.println(temp);
if (MAX_PHYSICAL_LENGTH == temp)
System.out.println("True statement");
else
System.out.println("False Statement");
}
}
The output is
9.9999992E7
False Statement
The question is
Whats wrong with the first code snip. Is this not plain mathematics
as far as float is concerned?
Why does it then give the expected output on the second code snip.
A typical (i.e. IEEE754) float only has 23 bits of precision. The other bits are for the exponent and the sign. The lowest integer that you can't store exactly is 1 plus the 24th power of 2.
100000000 - 4 is indistinguishable from 100000000 - 0.
A Java double gives you 52 bits of precision, therefore enough space to store all integers exactly up to the 53rd power of 2.
For more details see Which is the first integer that an IEEE 754 float is incapable of representing exactly?
But if you need exact decimal accuracy, then use a decimal type.
In my class I tried to return the sum of: 2^n + 2^(n+1) + 2^(n+2) ... in 2 ways.
Iterative in the first method and recursive in the 2nd one.
This worked as long as numbers weren't too big. Can someone explain to me why those methods return different answers when used with high numbers?
public class Power
{
public static void main(String[] args)
{
System.out.println(iterativ(3));
System.out.println(rekursiv(3));
System.out.println(iterativ(40));
// The recursive one is lower by 10
System.out.println(rekursiv(40));
}
public static int iterativ(int x)
{
int sum = 0;
for (int i = 0; i <= x; i++) {
sum += Math.pow(2, i);
}
return sum;
}
public static int rekursiv(int x)
{
if (x > 0) {
return ((int) Math.pow(2, x) + rekursiv(x - 1));
}
return 1;
}
}
You are using functions that deal with double. You are casting your values to int. Casting values will sooner or later always lead to some inaccurate results, even more so, if you cast from double to int.
The number you were seeing when using 40 as your exponent, was 2147483647, which is in fact Integer.MAX_VALUE, but isn't 2^40. It is rather 2^31-1. The java tutorial has a chapter about the primitive datatypes, which shows you the ranges of each type.
Besides using double you may also want to look at BigDecimal instead.
I am trying to beautify a program by displaying 1.2 if it is 1.2 and 1 if it is 1 problem is I have stored the numbers into the arraylist as doubles. How can I check if a Number is a double or int?
Well, you can use:
if (x == Math.floor(x))
or even:
if (x == (long) x) // Performs truncation in the conversion
If the condition is true, i.e. the body of the if statement executes, then the value is an integer. Otherwise, it's not.
Note that this will view 1.00000000001 as still a double - if these are values which have been computed (and so may just be "very close" to integer values) you may want to add some tolerance. Also note that this will start failing for very large integers, as they can't be exactly represented in double anyway - you may want to consider using BigDecimal instead if you're dealing with a very wide range.
EDIT: There are better ways of approaching this - using DecimalFormat you should be able to get it to only optionally produce the decimal point. For example:
import java.text.*;
public class Test
{
public static void main(String[] args)
{
DecimalFormat df = new DecimalFormat("0.###");
double[] values = { 1.0, 3.5, 123.4567, 10.0 };
for (double value : values)
{
System.out.println(df.format(value));
}
}
}
Output:
1
3.5
123.457
10
Another simple & intuitive solution using the modulus operator (%)
if (x % 1 == 0) // true: it's an integer, false: it's not an integer
I am C# programmer so I tested this in .Net. This should work in Java too (other than the lines that use the Console class to display the output.
class Program
{
static void Main(string[] args)
{
double[] values = { 1.0, 3.5, 123.4567, 10.0, 1.0000000003 };
int num = 0;
for (int i = 0; i < values.Length; i++ )
{
num = (int) values[i];
// compare the difference against a very small number to handle
// issues due floating point processor
if (Math.Abs(values[i] - (double) num) < 0.00000000001)
{
Console.WriteLine(num);
}
else // print as double
{
Console.WriteLine(values[i]);
}
}
Console.Read();
}
}
Alternatively one can use this method too, I found it helpful.
double a = 1.99;
System.out.println(Math.floor(a) == Math.ceil(a));
You can use:
double x=4;
//To check if it is an integer.
return (int)x == x;