I have an assignment for class where I need to write a method which calculates a Geometric progression for n integers using recursion.
The value of n is received from the user.
public static float Geometric(float n)
{
if(n==0)
return 1;
else
{
if(n == 1)
System.out.println(n);
else
return (n * Geometric(n-1));
}
}
The code works fine, until the value of n exceeds 34. Then, the method starts returning wrong answers. I'm assuming it has to do with the maximum value that a float can hold.
Is there a way to calculate/store values that exceed the maximum value of the primitive data types?
It seems to me that recursion isn't a good way to calculate a geometric progression, but maybe I'm just missing something. Any suggestions?
Thanks!
Welcome to StackOverflow!
For dealing with massive numbers, you can try looking at BigDecimal or BigInteger class. There is also another StackOverflow question (Finding the factorial using recursion with the BigInteger Class) that should be quite similar to your case
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
How is the gcd function below working I do not understand what the ger varible does. Also what is the lcm varible doing I find this function hard to understand I am not good at math.
long lcm,hcf = 0;
long i=1;
// This sets ger to max(a,b) - why?
long ger=a>b?a:b;
// This would return a wrong result if a == b
// that never happens here, though
while(i<ger)
{
if((a%i==0) && (b%i==0))
hcf=i;
i++;
}
lcm=(a*b)/hcf;
return lcm;
Unfortunately, this is not a very good implementation of finding the Greatest Common Divisor (GCD). I suggest you look up Euclid's method on WikiPedia.
The way the above works is the program continues to divide both numbers by increasing values of i starting with 1. When both a and b are divisible by i, i is assigned to hcf and the loop continues until i exceeds the larger of a and b. The last assignment to hcf is the GCD.
The Least Common Multiple (LCM) is the smallest number that is divisible by both a and b and is computed mathematically as the product of a and b divided by their greatest common divisor.
The % sign in java means for a % i get the remainder. So if the remainder of both a and b when divided by i is zero, then i would be the GCD.
Updated Answer
Although I don't like the above approach, the idea can still be improved in several ways which I will identify and explain here. (Euclid's method would still be better).
Don't find the largest of a and b, find the smallest. Why keep iterating from or toward a larger termination point? No value larger than v will ever divide v. So stop as soon as the smaller value is exceeded.
Don't iterate starting at 1 and increasing toward the smaller number. Start with the smaller number and decrease until you hit the first successful test. That would be the GCD of both numbers.
Don't do this (a*b)/gcd to get the LCM. It is possible that a*b could overflow a long. Since it is known that the gcd divides both, divide one of the values by gcd and then multiply by the other.
Here is the code with the changes.
public static long lcm(long a, long b) {
// find min(a,b)
long hcf = a<b?a:b;
// just loop and decrement
for (;; hcf--) {
if((a%hcf==0) && (b%hcf==0)) {
// guaranteed to exit
// when hcf reaches 1
break;
}
}
return a*(b/hcf);
}
1) I do not understand what the ger variable does?
long ger = a > b ? a : b; is supposed to set an upper bound for the following while-loop.
However
as you've already noted, it's wrong in combination with the while-condition while(i < ger) (wrong result when a == b)
and actually taking the maximum of the two integers is not making any sense as the upper bound should be the min(a, b) as the greatest common divisor of them cannot be larger than their minimum.
The while-loop finds the GCD by finding incrementally the largest divisor i (= GCD) which divides a and b without any remainder, i.e (a % i == 0) && (b % i == 0).
2) Also what is the lcm variable doing?
The lcm variable is the Least Common Multiple of two integers and can be computed using the Greatest Common Divisor (GCD = HCF). Simply put, it's just a formula.
Conclusion
So, the purpose of this function is to compute the LCM by first computing the GCD and then applying the formula: a × b = gcd(a, b) × lcm(a, b) Proof ⟶ lcm(a, b) = a × b / gcd(a, b)
5! = 5*4*3*2*1.
I have no problem with this. But I noticed with my program that if I type in say 3.5! it would return a defined number.
How do you calculate them?
I have something like this in my program
public class fact {
public static void main(String args[]) {
double factorial=1;
System.out.println("Type a number");
double number= sc.nextDouble(); /*I am using scanner*/
while (number !=0 ){
factorial = factorial * number;
number--;
}
System.out.println(factorial);
}
}
Factorial in its normal definition is defined only for positive integers. If you want to calculate factorials for any real numbers, have a look at Gamma functions.
https://en.wikipedia.org/wiki/Gamma_function
Thing is: factorial is pretty simple for whole, positive numbers.
The concept can also be applied for floating point numbers, but the math behind that could be considered advanced.
So: step back; and understand the math behind the concept; before implementing the concept!
In other words; you have to decide whether you intend to change your program to work with int numbers (validated to be > 0 ); or if you intend to allow floating point numbers. If the later is your goal; then your simple implementation won't do any more.
Beyond that: you want to study the concept of floating point numbers in the first place. It is a misconception to assume that a loop like
double number = ...
while (number !=0 ) {
..
number--;
}
would always stop when using floating point numbers instead of int/long! To the contrary ...
You are getting the defined value even for 3.5!, because your code will calculate it as following:
1*3.5*2.5*1.5*0.5
But actually it is wrong value for 3.5!. The correct value is: 11.6317283966. Your method is only valid for integer inputs. See this for more information about decimal factorials:
this link
Here, I am finding number of perfect square numbers in given range.
But I am dealing with 'for' loop execution that takes much time for execution.
The index/key traverses from two numbers, lets say A to B, and does some operation in for loop.
The problem arises when there's large difference between A and B (e.g. A = 2 & B = 100000)
Can u suggest how can I reduce or optimize the execution time?
Scanner in = new Scanner(System.in);
int A = in.nextInt();
int B = in.nextInt();
int cnt = 0;
for(int number =A ; number<= B; number++){
int sqrt = (int) Math.sqrt(number);
if(sqrt*sqrt == number) {
cnt++;
}
}
System.out.println(cnt);
Or is it because of Math class operations that takes too much time to execute?
Can you suggest any alternate approach to find the square numbers between given range?
Thanks in advance!
I found an alternate way to find the count of perfect square numbers between given range.
This can be simply achieve by using Math.floor and Math.ceil operations.
Math.floor(Math.sqrt(B)) - Math.ceil(Math.sqrt(A)) + 1
Thanks! :)
Instead of going through each number in the range and figuring out if its a perfect square, I would suggest the below
Find a square root of the start number and find the integer part of it.
Lets say start number is 5. So integer part of the square root will be 2.
Now do the same for the range end number
Lets say end range was 1000, so the integer part of its square root would be 31. Now iterate from 2+1 to 31 and keep printing its square. That would give you the perfect squares between the given range.
Instead of the if(sqrt * sqrt == number) you could also check whether the double returned by Math.srt(number) is a integer. The algorithm would than become as follows:
for(int number =A ; number<= B; number++){
if((Math.sqrt(number) % 1) == 0) {
cnt++;
}
}
Note: Haven't tried the code myself so might not work as I expect.
Regarding the question on how you can improve the performance. The checking on whether the number is perfect could be done in parallel by executing per number a task. The access to the counter has to be synchronized than, (to be on the safe side).
I am trying to create a recursive method that uses Horner's algorithm to convert a fractional number in base n to base 10. I've searched here and all over but couldn't find anywhere that dealt with the fractional part in detail. As a heads up, I'm pretty weak in recursion as I have not formally learned it in my programming classes yet, but have been assigned it by another class.
I was able to make a method that handles the integer part of the number, just not the fractional part.
I feel like the method I've written is fairly close as it gets me to double the answer for my test figures (maybe because I'm testing base 2).
The first param passed is an int array filled with the coefficients. I'm not too concerned with the order of the coefficients as I'm making all the coefficients the same to test it out.
The second param is the base. The third param is initialized to the number of coefficients minus 1 which I also used for the integer part method. I tried using the number of coefficients, but that steps out of the array.
I tried dividing by the base one more time as that would give me the right answer, but it doesn't work if I do so in the base case return statement or at the end of the final return statement.
So, when I try to convert 0.1111 base 2 to base 10, my method returns 1.875 (double the correct answer of 0.9375).
Any hints would be appreciated!
//TL;DR
coef[0] = 1; coef[1] = 1; coef[2] = 1; coef[3] = 1;
base = 2; it = 3;
//results in 1.875 instead of the correct 0.9375
public static double fracHorner(int[] coef, int base, int it) {
if (it == 0) {
return coef[it];
}
return ((float)1/base * fracHorner(coef, base, it-1)) + coef[it];
}
Observe that fracHorner always returns a value at least equal to coef[it] because it either returns coef[it] or something positive added to coef[it]. Since coef[it] >= 1 in your tests, it will always return a number greater than or equal to one.
It's relatively easy to fix: divide both coef[it] by base:
public static double fracHorner(int[] coef, int base, int it) {
if (it == 0) {
return ((double)coef[it])/base;
}
return (fracHorner(coef, base, it-1) + coef[it])/base;
}
I would like to build a method that outputs 1000 if the input number is thousands (eg. 3458), 100 if the input number is hundreds and so on. Is this possible?
Of course it is possible. Why don't you post what you tried and we can give you pointers on how to solve any problems.
As Steve said, it's probably a good idea to give it a little try yourself first, then come to SO with a specific question (i.e. "I am doing X, this is my code, why isn't Y happening?").
However, as a small hint, assuming you have pure numeric input (i.e. it will always just be a stream of numbers, with no ","s or the like) you can actually do the working out using just strings - no need for working with numerical types (int, etc) at all...
(Okay, thinking about this, there might be a little math right at the end to get the final result of '100' or '1000' etc, but not much.)
To expand on what Yuval offered, if you don't care about the sign of the number (that is, input values of, say, +3456 and -3456 should both return 1000), you can just use the absolute value of the input:
return Math.pow(10, Math.floor(Math.log( Math.abs(n) ) / Math.log(10))); // for input n
And if you want to handle all possible numeric inputs, you could also handle the zero-value before doing your calculation:
if (n == 0) // for input n
return 0;
return Math.pow(10, Math.floor(Math.log( Math.abs(n) ) / Math.log(10))); // for input n
log(0) is undefined, so you don't want to perform the calculation if n == 0. You'll get a funny answer (if you even get an answer... I didn't run this code). Given the description of the problem you provided, I think returning 0 when the input is 0 makes sense. Zero isn't in the thousands or the hundreds or the tens or the ones -- among the integers, it is its own category. So you could return 0. Or you could throw an exception.
Its not fancy, but its simple and readable.
private static void homework(int n) {
if (n > 9999) {
System.out.println("Really big");
} else {
if (n <= 99 ) {
System.out.println("Really small");
} else if (n <= 999) {
System.out.println("Hundred");
} else if ( n <= 9999) {
System.out.println("Thousand");
} else {
System.out.println("How did this get here? I'm not good with computer!");
}
}
}
Simple math:
Math.pow(10, Math.floor(Math.log(n) / Math.log(10))) // for given n
A loop can be used to avoid using double and an eventual rounding problem (if transforming the result to int).
The loop variable starts with 1 and is multiplied by 10 each pass while the (next) result is less than the input number.
Negative and zero input need a special handling.