Floating point inaccuracy during e calculation with numerical methods - java

So i was calculating e(third row in picture) with numerical methods.
I was increasing the number of elements i used every iteration. And when i executed the program, floating point variable behaved in a way i didn't understand. Here is the program and the result.
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int factorial = 1;
int counter = 0;
int iterationNumber;
double total = 0;
int tempCounter;
System.out.print("Enter iteration number: ");
iterationNumber = input.nextInt();
while (counter <= iterationNumber) {
tempCounter = counter;
while ((tempCounter - 1) > 0) {
factorial *= tempCounter;
tempCounter--;
}
total += ((double)1 / factorial);
System.out.println(total);
factorial = 1;
counter ++;
}
}
}
So my question is why does the value of e starts to decrease after a while instead of increasing? I want to learn how floating point variable behaves during this program and the logic behind it.
Another question is why does it start to say infinity?

n! quickly exceeds Integer.MAX_VALUE and overflows to a negative number. You are then adding a negative number to your total --- thus the decrease.
You can use BigDecimal for your calcualtions. It is slower, but will do the job.

Related

Method works but throws errors for particular numbers

I wrote a method that calculates the combination of 2 numbers and it works for smaller numbers where n = 10 and r = 3, but when input n as 100 and r as 3 it throws an arithmetic exception
" / by zero"
import java.util.Scanner;
public class Combination {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.print("Enter n: ");
int n = scan.nextInt();
System.out.print("\nEnter r: ");
int r = scan.nextInt();
scan.close();
int ans = factorial(n) / (factorial((n-r)) * factorial(r));
System.out.print("\nThe combination is: "+ans);
}
static int factorial(int num) {
for(int i = num; i>1; --i) {
num *= (i - 1);
}
return num;
}
}
but i don't know what the problem is. it works for smaller numbers of n.
You're multiplying values which result in a number too big to fit inside an integer.
If you print out the num inside your for loop, you'll notice it eventually either goes negative or to zero. This is due to overflow.
For your example of n=100 and r=3 not even long will do. You'll need to use something like BigInteger.
Keep in mind that using BigInteger will drastically slow down your program when compared to using primitives.
If you're not interested in having such large numbers and were just curious why it wasn't working, you can also use Math.multiplyExact(int x, int y) or Math.multiplyExact(long x, long y) if you're using Java 8 or above.
By using these methods, you'll avoid having to deal with the side-effects of overflow since they will throw an ArithmeticException if the result overflows.
Change the data type of num from int to double

Java Euler number result infinity

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.

Average Calculator [ rounding issues ]

I have been assigned a task to create a average calculator, unfortunately each time a average is done I get either one too many which doesn't fix the issue when I do number -- OR, the average is completely off.
import java.util.*;
public class Mean
{
public static void main()
{
Scanner inputLine = new Scanner(System.in);
int total = 0, number, counter = 0;
double average;
System.out.println ("Enter your numbers, press 0 to launch");
while (inputLine.nextInt() != 0)
{
number = inputLine.nextInt();
if(number >= 1)
{
total = total + number;
counter++;
}
}
average = total/counter-1;
System.out.println ("Your Average is : " + average);
}
}
You are reading an int from the Scanner twice per loop. The while loop reads an int to make sure it's not 0, but then the body of the while loop reads a second int and only counts that second int.
Assign the result of the first nextInt call to a variable in the while loop condition, and use that variable in the body for the calculations.
You are subtracting 1 from your average calculation. There's no reason for that. Don't do it.
You are performing Java's integer division, which will truncate any decimals. Cast one of the operands to / to double to force floating-point calculations.
while ( (number = inputLine.nextInt() ) != 0)
{
if(number >= 1)
{
total = total + number;
counter++;
}
}
average = (double) total / counter;
You may want to add code for a condition where the user entered no items, to prevent dividing by 0.

Understanding methods. Java code

Write a method that computes the sum of the digits in an integer. Use
the following method header: public static int sumDigits(long n)
Programming problem 5.2. Page 212.
Please forgive my newness to programming. I'm having a hard time understanding and answering this question. Here's what I have so far. Please assist and if you dont mind, explain what I'm doing wrong.
import java.util.Scanner;
public class PP52v2 {
public static void main(String [] args) {
int sum = sumDigits(n);
System.out.println("The sum is: " + sum);
}//main
public static int sumDigits(long n) {
Scanner input = new Scanner(System.in);
System.out.println("Enter your digits");
n = input.nextLong();
int num = (int)(n);
int sum;
while(num > 0) {
sum += num % 10; //must mod - gives individual numbers
num = num / 10; //must divide - gives new num
}//loop
return sum;
}//sumDigits
}//class
Basically, you should not be handling the user input inside of the method. You should be passing the user input into your method. Other than that, everything looks good. I've made that slight change below:
import java.util.Scanner;
public class PP52v2 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("Enter your digits");
long n = input.nextLong();
int sum = sumDigits(n);
System.out.println("The sum is: " + sum);
}// main
public static int sumDigits(long n) {
int num = (int) (n);
int sum = 0;
while (num > 0) {
sum += num % 10; // must mod - gives individual numbers
num = num / 10; // must divide - gives new num
}// loop
return sum;
}// sumDigits
}// class
Do the prompt
System.out.println("Enter your digits");
n = input.nextLong();
in your main(String[] args) method because n is not currently declared in the scope of the main method.
public static int sumDigits(int num) {
int sum = 0;
while(num > 0) {
sum += num % 10; //must mod - gives individual numbers
num = num / 10; //must divide - gives new number
} //End loop
return sum;
}
For one, you should not read in the number within this method, as it accepts the number as a parameter. The method should be invoked after calling long inputNum = input.nextLong(); by using int digitSum = sumDigits((int)inputNum).
When writing a method, you have input, output, and side effects. The goal is to choose the right combination of the three so that the method, and program as a whole, words as expected.
It seems like your method is supposed to take a number as input and return each digit added together into one final sum.
Write A Test
Usually when you program, you come up with some code that uses your imaginary function. This is called a test. For a test, this could work:
System.out.println("123 should be 6: " + sumDigits(123));
Choose A Signature
You've already managed to right the correct signature. Nice!
Implement Method
Here's where you're a bit confused. Read through what every line of code does, and see if it is accomplishing your goal.
// set up a scanner for reading from the command line
// and print a message that you expect digits
Scanner input = new Scanner(System.in);
System.out.println("Enter your digits");
// read the next long number from the input stream
n = input.nextLong();
Why is this part of your method? You already have the number passed in as the argument n.
// cast the number to an integer
int num = (int)(n);
Again, not sure what this is accomplishing, besides the possibility of a bug for large numbers.
// initialize the sum variable to 0.
int sum;
Would be clearer to explicitly set the sum to 0. int sum = 0;
// add the last digit and truncate the number in a loop
while(num > 0) {
sum += num % 10; //must mod - gives individual numbers
num = num / 10; //must divide - gives new num
}
// actually return the calculated sum
return sum;
This seems like the only part of the method you need. Hopefully this helps!
Since the input number can be either positive or negative, you need to convert it to its absolute value to get the sum of digits. Then for each iteration, you add the remainder to the total sum until the quotient is 0.
public static int sumDigits(long n) {
int sum = 0;
long quotient = Math.abs(n);
while(quotient > 0) {
sum += quotient % 10;
quotient = (long) quotient / 10;
}
return sum;
}
Your code works fine for me.
i just changed int sum = sumDigits(n) to int sum = sumDigits(0) since n wasn't declared.
To have it done correctly, you just would have to put your scanner into the main method and pass the result of it (the long value) to your method sumDigits(long n).

Java - Add all odd numbers strange behaviour

I am doing a maths challenge for project euler and i have come across a strange problem when running the program. The result should be the sum of all the odd numbers up to 10,000,000 but i get a negative number, what am i doing wrong?
package program;
import java.util.*;
public class MainClass {
/**
* #param args
*/
public static void main(String[] args) {
int total = 0;
for (int counter = 1; counter < 10000000; counter++) {
if (!((counter % 2) == 0)) {
total+=counter;
}
}
System.out.println(total);
}
}
Use a long instead of an int. You're getting a negative number due to integer overflow.
The int variable can't hold the total because the total is too big. At some point in the loop, you're getting an integer overflow and it's "rolling over" to a negative number:
You need a long.
A matter of style and efficiency, I'd change the code to iterate by 2 so that you don't need the test for oddness:
public static void main(String[] args) {
long total = 0;
for (int counter = 1; counter < 10000000; counter += 2) { // iterate by 2
total += counter;
}
System.out.println(total);
}
You should use long total = 0; instead of int total = 0; int in java is 4 bytes and ranges from -2,147,483,648 to 2,147,483,647.
so 2,147,483,647 + 1 = -2,147,483,648
The total for this loop comes out to be 25,000,000,000,000 which can be accommodated by long
Just to throw in the more clever solution to this problem (MATH! yay).
You can solve this much easier, you just need to know that the sum of odd numbers from 1..2n-1 is equal to the square of n. It's pretty easy to prove this with induction for those who want to try.
Anyways this means that the sum from 1..X is equal to: ((X + 1) / 2)**2

Categories