adding fractions using recursion e=1+1/1!+1/2!+1/3!+ - java

I need to write a recursive method to compute the following series:
e = 1+1/1!+1/2!+1/3!+...
This is what I have so far.
public static void main(String[] args)
{ System.out.println("enter n :");
int n =scan.nextInt();
double h = fact(n);
System.out.println(" e = ");
}
public double fact(int n)
{
if (n == 1)
return 1;
else
return ???;
}
}

So, assuming the n input you're taking is the starting denominator for the smallest fraction you'd add...
(For example, given n = 10, you want to add 1 through 1/10)
Then you need to set up your method so that when you call fact(10), it's going to return the sum of 1/10 plus the result of fact(9), or more generically, 1/n + fact(1/n-1);
So, you're looking for something like this:
public double fact(int n) {
if (n < 0) {
return 0.0;
} else if (n == 0) {
return 1.0;
} else {
return (1.0/n + fact(n-1))
}
}
Also, please note the changes to the base cases. When n < 0, we just return 0.0, because if I recall correctly, the factorial of any negative number is always 0, right?
Meanwhile, the base case should be n==0, not n == 1. Your series starts with 1 + 1/1. Note that 1 is not 1/0 or 1/nothing, it's just 1/1. We can't return 1/n when n is 0. For the series to calculate correctly, we have to add the first return the first element of the series in the case of n = 0.
And keep in mind, as with all recursive functions, very large values of n will cause a stack overflow.

Here are a couple of resources:
Math is fun
"Yes you can! But you need to get into a subject called the "Gamma
Function", which is beyond this simple page.
Half Factorial
But I can tell you the factorial of half (½) is half of the square
root of pi = (½)√π, and so some "half-integer" factorials are:"
More specifically you want the Gamma Function
Apache commons has an implementation of this function.
Discussion on Math Exchange
And here is an implementation from Princeton
public class Gamma {
static double logGamma(double x) {
double tmp = (x - 0.5) * Math.log(x + 4.5) - (x + 4.5);
double ser = 1.0 + 76.18009173 / (x + 0) - 86.50532033 / (x + 1)
+ 24.01409822 / (x + 2) - 1.231739516 / (x + 3)
+ 0.00120858003 / (x + 4) - 0.00000536382 / (x + 5);
return tmp + Math.log(ser * Math.sqrt(2 * Math.PI));
}
static double gamma(double x) { return Math.exp(logGamma(x)); }
public static void main(String[] args) {
double x = Double.parseDouble(args[0]);
System.out.println("Gamma(" + x + ") = " + gamma(x));
System.out.println("log Gamma(" + x + ") = " + logGamma(x));
}
}

Calculating e^n recursively is very expensive. It is O(n^2) and it is hard to know when to stop. Instead I suggest you do it iteratively.
static final int runs = 20000;
static volatile int exp = 1;
static volatile int n = 18;
static volatile double dontOptimiseAway;
public static void main(String[] args) throws InterruptedException {
System.out.println("Math.exp(1)=" + Math.exp(1));
System.out.println("exp_iter(18)=" + exp_iter(18));
System.out.println("exp_recurse(18)=" + exp_recurse(18));
for (int t = 0; t < 3; t++) {
System.out.printf("exp(1), exp_iter(18), exp_recurse(18) took %,d / %,d / %,d ns on average%n",
timeMathExp(), timeExpIter(), timeExpRecurse());
}
}
public static long timeMathExp() {
long start = System.nanoTime();
for (int i = 0; i < runs; i++)
dontOptimiseAway = Math.exp(exp);
return (System.nanoTime() - start) / runs;
}
public static long timeExpIter() {
long start = System.nanoTime();
for (int i = 0; i < runs; i++)
dontOptimiseAway = exp_iter(n);
return (System.nanoTime() - start) / runs;
}
public static long timeExpRecurse() {
long start = System.nanoTime();
for (int i = 0; i < runs; i++)
dontOptimiseAway = exp_recurse(n);
return (System.nanoTime() - start) / runs;
}
public static double exp_iter(int n) {
double exp = 0, x = 1;
for (int i = 2; i <= n; i++)
exp += (x /= i);
return 2 + exp;
}
public static double exp_recurse(int n) {
return n <= 0 ? 1 : 1.0 / fact(n) + exp_recurse(n - 1);
}
public static double fact(int n) {
return n <= 1 ? 1 : n * fact(n - 1);
}
prints
Math.exp(1)=2.718281828459045
exp_iter(18)=2.718281828459045
exp_recurse(18)=2.7182818284590455
exp(1), exp_iter(18), exp_recurse(18) took 111 / 191 / 760 ns on average
exp(1), exp_iter(18), exp_recurse(18) took 75 / 78 / 558 ns on average
exp(1), exp_iter(18), exp_recurse(18) took 69 / 66 / 552 ns on average

write the code as below and call it from main class.
public static double recursiveFun(double value){
if (value==1)
return 1.0;
if (value==2){
return (1/(value-1) + 1/value);
}
else
return recursiveFun(value-1) + 1/value;
}

Related

How can I summarize the probability results, that I got with a loop? (Java)

I'm wondering if is there a way to summarize the results of probability that I got through a loop? So I can know how many successful hits there were, given x number of attempts. Right now I just get a stream of 1 or 0 statements (1 for a successful hit, 0 for fail), not very practical. It looks like this:
public class doGry {
public static void main(String[] args ) {
for (int i = 0; i < 50; i++) {
// chance to hit (h) = 35% + (ma - md)
// 8% < h < 90%
double ma = 20;
double md = 10;
double probability;
System.out.println("probability of success " + (probability = 35 + (ma - md)));
double probab2 = probability / 100;
double r = Math.random();
int roll;
if (r <= probab2) roll = 1;
else roll = 0;
System.out.println(roll);
}
}
}
There are few variables that can be initialized outside of for-loop since you are not modifying its value, so no need it initialize it again and again.
Using a variable count, for keeping track of successful hits. For each successful hit, increment its value by 1.
public class doGry {
public static void main(String[] args ) {
double ma = 20;
double md = 10;
double probability = 35 + (ma - md);
double probab2 = probability / 100;
int count = 0;
for (int i = 0; i < 50; i++) {
System.out.println("probability of success " + probability);
double r = Math.random();
if (r <= probab2)
{
System.out.println("1");
count++;
}
else
System.out.println("0");
}
System.out.println("Succesful hits " + count);
}
}
All you have to do is add in a variable to keep track of how many successful rolls occurred, and then divide that by the total number of rolls using a double like so
public class doGry
{
public static void main(String[] args )
{
int total = 0;
for (int i = 0; i < 50; i++)
{
// chance to hit (h) = 35% + (ma - md)
// 8% < h < 90%
double ma = 20.0;
double md = 10.0;
double probability;
System.out.println("probability of success " + (probability = 35 + (ma - md)));
double probab2 = probability / 100;
double r = Math.random();
int roll;
if (r <= probab2) {roll = 1; total++;}
else roll = 0;
System.out.println(roll);
}
System.out.println("total: " + total/50.0);
}
}
Notice in the final System.out.println statement, the total is being divided by 50.0 (and not 50) as the .0 indicates you want a double division and not integer division, the latter of which throws away any remainder decimal values.

Finding the sum of multiples of any number less than the specified number. Where is my mistake?

This is my another solution where the output is shown as expected
public class Logic2 {
public static void main(String[] args) {
long sum = 0;
calculation key = new calculation();
sum = key.sum(3, 1000);
System.out.print(sum);
}
}
class calculation {
long total = 0;
public long sum(int num, int limit) { //multples of num less than limit
int number = Integer.valueOf(limit / num);
if (limit % num == 0) {
number -= 1;
}
total = (number / 2) * (2 * num + (number - 1) * num);
return total;
}
}
I wrote this code myself. It seems everything fine but I am not getting the required output. Why is this so?
It looks like your math is just slightly wrong. Try breaking it up into smaller parts to confirm you're getting what you're expecting. A working example which returns 166833
public static void main(String[] args) {
int a = 3, N = 1000;
System.out.println("Sum of multiples of " + a +
" up to " + N + " = " +
calculate_sum(a, N));
}
private static int calculate_sum(int a, int N) {
// Number of multiples
int m = N / a;
// sum of first m natural numbers
int sum = m * (m + 1) / 2;
// sum of multiples
return a * sum;
}
If you split your method up the same way, you will see where you've missed the mark slightly.
public class Logic2 {
public static void main(String[] args) {
long sum = 0;
calculation key = new calculation();
sum = key.sum(3, 1000);
System.out.print(sum);
}
}
class calculation {
long total = 0;
public long sum(int num, int limit) { //multples of num less than limit
int number = Integer.valueOf(limit / num);
if (limit % num == 0) {
number -= 1;
}
total=((number)*(2*num+(number-1)*num))/2;
//previouslly total = (number / 2) * (2 * num + (number - 1) * num);
return total;
}
}
I figured out the bug myself. In that, Total if we write (number/2) then it will give integer value due to which I was not getting the required output. Anyways, Thanks everyone for at list viewing my post, I appreciate it. :)

Java Program to determine value of nested radical constant with 10^-6 precision

Nested radical constant is defined as:
I am writing a Java program to calculate the value of nested radical constant with 10^-6 precision and also print the number of iterations required to get to that precision. Here is my code:
public class nested_radical {
public nested_radical() {
int n = 1;
while ((loop(n) - loop(n - 1)) > 10e-6) {
n++;
}
System.out.println("value of given expression = " + loop(n));
System.out.println("Iterations required = " + n);
}
public double loop(int n) {
double sum = 0;
while (n > 0) {
sum = Math.sqrt(sum + n--);
}
return (sum);
}
public static void main(String[] args) {
new nested_radical();
}
}
This code does what it is supposed to but it is slow. What should I do to optimize this program? Can someone suggest another possible way to implement this program?
I also want to write a same kind of program in MATLAB. It would be great if someone could translate this program into MATLAB too.
I have made some changes in this code and now it stores the value of loop(n - 1) instead of computing it every time. Now this program seems much optimized than before.
public class nested_radical {
public nested_radical() {
int n = 1;
double x = 0, y = 0, p = 1;
while ( p > 10e-6) {
y=x; /*stored the value of loop(n - 1) instead of recomputing*/
x = loop(n);
p = x - y;
n++;
}
System.out.println("value of given expression = " + x);
System.out.println("Iterations required = " + n);
}
public double loop(int n) {
double sum = 0;
while (n > 0) {
sum = Math.sqrt(sum + n--);
}
return (sum);
}
public static void main(String[] args) {
new nested_radical();
}
}
I also successfully translated this code in MATLAB. Here is the code for MATLAB:
n = 1;
x = 0;
p = 1;
while(p > 10e-6)
y = x;
sum = 0;
m=n;
while (m > 0)
sum = sqrt(sum + m);
m = m - 1;
end
x = sum;
p = (x-y);
n = n + 1;
end
fprintf('Value of given expression: %.16f\n', x);
fprintf('Iterations required: %d\n', n);

Return how many terms are necessary entering a level of precision, e.g .001, to come within the specified precision of the value of PI?

Problem: Interactively enter a level of precision, e.g., .001, and then report how many terms are necessary for each of these estimates to come within the specified precision of the value of pi.
My Solution So Far:
Current result does not terminate. The PIEstimator class driver is given. The problem lies inside the PIEstimates class. Some specific questions that I have:
How do you calculate Wallis PI and Leibniz PI in code? The ways for calculating each arithmetically for Wallis is:
pi/4 = (2/3)(4/3)(4/5)(6/5)(6/7)(8/7)(8/9)*...
and for Leibniz:
pi/4 = (1 - 1/3 + 1/5 - 1/7 + 1/9 ...)
Is the current logic of doing this code correct so far? Using a while loop to check if the respective PI calculation is within the limits, with a for loop inside continuing to run until the while requirements are met. Then there is a count that returns the number of times the loop repeated.
For .001, for example, how many terms does it take for each of these formulas to reach a value between 3.14059.. and 3.14259...
import java.util.Scanner;
public class PiEstimator {
public static void main(String[] args) {
System.out.println("Wallis vs Leibnitz:");
System.out.println("Terms needed to estimate pi");
System.out.println("Enter precision sought");
Scanner scan = new Scanner(System.in);
double tolerance = scan.nextDouble();
PiEstimates e = new PiEstimates(tolerance);
System.out.println("Wallis: " + e.wallisEstimate());
System.out.println("Leibnitz: " + e.leibnitzEstimate());
}
}
public class PiEstimates {
double n = 0.0;
double upperLim = 0;
double lowerLim = 0;
public PiEstimates(double tolerance) {
n = tolerance;
upperLim = Math.PI+n;
lowerLim = Math.PI-n;
}
public double wallisEstimate() {
double wallisPi = 4;
int count = 0;
while(wallisPi > upperLim || wallisPi < lowerLim) {
for (int i = 3; i <= n + 2; i += 2) {
wallisPi = wallisPi * ((i - 1) / i) * ((i + 1) / i);
}
count++;
}
return count;
}
public double leibnitzEstimate() {
int b = 1;
double leibnizPi = 0;
int count = 0;
while(leibnizPi > upperLim || leibnizPi < lowerLim) {
for (int i = 1; i < 1000; i += 2) {
leibnizPi += (4/i - 4/i+2);
}
b = -b;
count++;
}
return count;
}
}
At least one mistake in wallisEstimate
for (int i = 3; i <= n + 2; i += 2) {
should be count instead of n:
for (int i = 3; i <= count + 2; i += 2) {
... but still then the algorithm is wrong. This would be better:
public double wallisEstimate() {
double wallisPi = 4;
int count = 0;
int i = 3;
while(wallisPi > upperLim || wallisPi < lowerLim) {
wallisPi = wallisPi * ((i - 1) / i) * ((i + 1) / i);
count++;
i += 2;
}
return count;
}
Similarly, for the Leibniz function:
public double leibnitzEstimate() {
double leibnizPi = 0;
int count = 0;
int i = 1;
while(leibnizPi > upperLim || leibnizPi < lowerLim) {
leibnizPi += (4/i - 4/i+2);
count++;
i += 4;
}
return count;
}
For Leibnitz, I think the inner loop should only run count number of times:
for (int i = 1; i < count; i += 2) {
leibnizPi += (4/i - 4/i+2);
}
If it runs 1000 times every time you can't know when pi was in range.
If the while loops don't terminate, then they don't approach PI.
Wallis: pi/4 = (2/3)(4/3)(4/5)(6/5)(6/7)(8/7)(8/9)*...
The while loop would restart the for loop at i = 3 which would keep adding the same sequence of terms, rather than progressing along with the pattern.
Here's a draft of an alternative solution (no pun intended) based on the pattern of terms.
As you see, the numerators repeat, except for the 2. The divisors repeat aswell, but offset from the numerators: they increment in an alternating fashion.
This way you can actually count each individual terms, instead of pairs of them.
public double wallisEstimate() {
double wallisPi = 1;
int count = 0;
double numerator = 2;
double divisor = 3;
while(wallisPi > upperLim || wallisPi < lowerLim) {
wallisPi *= numerator / divisor;
if ( count++ & 1 == 0 )
numerator+=2;
else
divisor+=2;
}
return count;
}
There is one more change to make, and that is in the initialisation of upperLim and lowerLim. The algorithm approaches PI/2, so:
upperLim = (Math.PI + tolerance)/2;
lowerLim = (Math.PI - tolerance)/2;
Leibniz: pi/4 = (1 - 1/3 + 1/5 - 1/7 + 1/9 ...)
Here the for loop is also unwanted: at best, you will be counting increments of 2000 terms at a time.
The pattern becomes obvious if you write it like this:
1/1 - 1/3 + 1/5 - 1/7 ...
The divisor increments by 2 for every next term.
public double leibnitzEstimate() {
double leibnizPi = 0;
int divisor = 1;
int count = 0;
while(leibnizPi > upperLim || leibnizPi < lowerLim) {
leibnizPi += 1.0 / divisor;
divisor = -( divisor + 2 );
count++;
}
return count;
}
The update of leibnizPi can also be written like this:
leibnizPi += sign * 1.0 / divisor;
divisor += 2;
sign = -sign;
which is more clear, takes one more variable and one more instruction.
An update to the upperLim and lowerLim must be made here aswell: the algorithm approaches PI/4 (different from Leibniz!), so:
upperLim = (Math.PI + tolerance)/4;
lowerLim = (Math.PI - tolerance)/4;

Way to get number of digits in an int?

Is there a neater way for getting the number of digits in an int than this method?
int numDigits = String.valueOf(1000).length();
Your String-based solution is perfectly OK, there is nothing "un-neat" about it. You have to realize that mathematically, numbers don't have a length, nor do they have digits. Length and digits are both properties of a physical representation of a number in a specific base, i.e. a String.
A logarithm-based solution does (some of) the same things the String-based one does internally, and probably does so (insignificantly) faster because it only produces the length and ignores the digits. But I wouldn't actually consider it clearer in intent - and that's the most important factor.
The logarithm is your friend:
int n = 1000;
int length = (int)(Math.log10(n)+1);
NB: only valid for n > 0.
The fastest approach: divide and conquer.
Assuming your range is 0 to MAX_INT, then you have 1 to 10 digits. You can approach this interval using divide and conquer, with up to 4 comparisons per each input. First, you divide [1..10] into [1..5] and [6..10] with one comparison, and then each length 5 interval you divide using one comparison into one length 3 and one length 2 interval. The length 2 interval requires one more comparison (total 3 comparisons), the length 3 interval can be divided into length 1 interval (solution) and a length 2 interval. So, you need 3 or 4 comparisons.
No divisions, no floating point operations, no expensive logarithms, only integer comparisons.
Code (long but fast):
if (n < 100000) {
// 5 or less
if (n < 100){
// 1 or 2
if (n < 10)
return 1;
else
return 2;
} else {
// 3 or 4 or 5
if (n < 1000)
return 3;
else {
// 4 or 5
if (n < 10000)
return 4;
else
return 5;
}
}
} else {
// 6 or more
if (n < 10000000) {
// 6 or 7
if (n < 1000000)
return 6;
else
return 7;
} else {
// 8 to 10
if (n < 100000000)
return 8;
else {
// 9 or 10
if (n < 1000000000)
return 9;
else
return 10;
}
}
}
Benchmark (after JVM warm-up) - see code below to see how the benchmark was run:
baseline method (with String.length):
2145ms
log10 method: 711ms = 3.02 times
as fast as baseline
repeated divide: 2797ms = 0.77 times
as fast as baseline
divide-and-conquer: 74ms = 28.99
times as fast as baseline
Full code:
public static void main(String[] args) throws Exception {
// validate methods:
for (int i = 0; i < 1000; i++)
if (method1(i) != method2(i))
System.out.println(i);
for (int i = 0; i < 1000; i++)
if (method1(i) != method3(i))
System.out.println(i + " " + method1(i) + " " + method3(i));
for (int i = 333; i < 2000000000; i += 1000)
if (method1(i) != method3(i))
System.out.println(i + " " + method1(i) + " " + method3(i));
for (int i = 0; i < 1000; i++)
if (method1(i) != method4(i))
System.out.println(i + " " + method1(i) + " " + method4(i));
for (int i = 333; i < 2000000000; i += 1000)
if (method1(i) != method4(i))
System.out.println(i + " " + method1(i) + " " + method4(i));
// work-up the JVM - make sure everything will be run in hot-spot mode
allMethod1();
allMethod2();
allMethod3();
allMethod4();
// run benchmark
Chronometer c;
c = new Chronometer(true);
allMethod1();
c.stop();
long baseline = c.getValue();
System.out.println(c);
c = new Chronometer(true);
allMethod2();
c.stop();
System.out.println(c + " = " + StringTools.formatDouble((double)baseline / c.getValue() , "0.00") + " times as fast as baseline");
c = new Chronometer(true);
allMethod3();
c.stop();
System.out.println(c + " = " + StringTools.formatDouble((double)baseline / c.getValue() , "0.00") + " times as fast as baseline");
c = new Chronometer(true);
allMethod4();
c.stop();
System.out.println(c + " = " + StringTools.formatDouble((double)baseline / c.getValue() , "0.00") + " times as fast as baseline");
}
private static int method1(int n) {
return Integer.toString(n).length();
}
private static int method2(int n) {
if (n == 0)
return 1;
return (int)(Math.log10(n) + 1);
}
private static int method3(int n) {
if (n == 0)
return 1;
int l;
for (l = 0 ; n > 0 ;++l)
n /= 10;
return l;
}
private static int method4(int n) {
if (n < 100000) {
// 5 or less
if (n < 100) {
// 1 or 2
if (n < 10)
return 1;
else
return 2;
} else {
// 3 or 4 or 5
if (n < 1000)
return 3;
else {
// 4 or 5
if (n < 10000)
return 4;
else
return 5;
}
}
} else {
// 6 or more
if (n < 10000000) {
// 6 or 7
if (n < 1000000)
return 6;
else
return 7;
} else {
// 8 to 10
if (n < 100000000)
return 8;
else {
// 9 or 10
if (n < 1000000000)
return 9;
else
return 10;
}
}
}
}
private static int allMethod1() {
int x = 0;
for (int i = 0; i < 1000; i++)
x = method1(i);
for (int i = 1000; i < 100000; i += 10)
x = method1(i);
for (int i = 100000; i < 1000000; i += 100)
x = method1(i);
for (int i = 1000000; i < 2000000000; i += 200)
x = method1(i);
return x;
}
private static int allMethod2() {
int x = 0;
for (int i = 0; i < 1000; i++)
x = method2(i);
for (int i = 1000; i < 100000; i += 10)
x = method2(i);
for (int i = 100000; i < 1000000; i += 100)
x = method2(i);
for (int i = 1000000; i < 2000000000; i += 200)
x = method2(i);
return x;
}
private static int allMethod3() {
int x = 0;
for (int i = 0; i < 1000; i++)
x = method3(i);
for (int i = 1000; i < 100000; i += 10)
x = method3(i);
for (int i = 100000; i < 1000000; i += 100)
x = method3(i);
for (int i = 1000000; i < 2000000000; i += 200)
x = method3(i);
return x;
}
private static int allMethod4() {
int x = 0;
for (int i = 0; i < 1000; i++)
x = method4(i);
for (int i = 1000; i < 100000; i += 10)
x = method4(i);
for (int i = 100000; i < 1000000; i += 100)
x = method4(i);
for (int i = 1000000; i < 2000000000; i += 200)
x = method4(i);
return x;
}
Again, benchmark:
baseline method (with String.length): 2145ms
log10 method: 711ms = 3.02 times as fast as baseline
repeated divide: 2797ms = 0.77 times as fast as baseline
divide-and-conquer: 74ms = 28.99 times as fast as baseline
Edit
After I wrote the benchmark, I took a sneak peak into Integer.toString from Java 6, and I found that it uses:
final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
99999999, 999999999, Integer.MAX_VALUE };
// Requires positive x
static int stringSize(int x) {
for (int i=0; ; i++)
if (x <= sizeTable[i])
return i+1;
}
I benchmarked it against my divide-and-conquer solution:
divide-and-conquer: 104ms
Java 6 solution - iterate and compare: 406ms
Mine is about 4x as fast as the Java 6 solution.
Two comments on your benchmark: Java is a complex environment, what with just-in-time compiling and garbage collection and so forth, so to get a fair comparison, whenever I run a benchmark, I always: (a) enclose the two tests in a loop that runs them in sequence 5 or 10 times. Quite often the runtime on the second pass through the loop is quite different from the first. And (b) After each "approach", I do a System.gc() to try to trigger a garbage collection. Otherwise, the first approach might generate a bunch of objects, but not quite enough to force a garbage collection, then the second approach creates a few objects, the heap is exhausted, and garbage collection runs. Then the second approach is "charged" for picking up the garbage left by the first approach. Very unfair!
That said, neither of the above made a significant difference in this example.
With or without those modifications, I got very different results than you did. When I ran this, yes, the toString approach gave run times of 6400 to 6600 millis, while the log approach topok 20,000 to 20,400 millis. Instead of being slightly faster, the log approach was 3 times slower for me.
Note that the two approaches involve very different costs, so this isn't totally shocking: The toString approach will create a lot of temporary objects that have to be cleaned up, while the log approach takes more intense computation. So maybe the difference is that on a machine with less memory, toString requires more garbage collection rounds, while on a machine with a slower processor, the extra computation of log would be more painful.
I also tried a third approach. I wrote this little function:
static int numlength(int n)
{
if (n == 0) return 1;
int l;
n=Math.abs(n);
for (l=0;n>0;++l)
n/=10;
return l;
}
That ran in 1600 to 1900 millis -- less than 1/3 of the toString approach, and 1/10 the log approach on my machine.
If you had a broad range of numbers, you could speed it up further by starting out dividing by 1,000 or 1,000,000 to reduce the number of times through the loop. I haven't played with that.
Can't leave a comment yet, so I'll post as a separate answer.
The logarithm-based solution doesn't calculate the correct number of digits for very big long integers, for example:
long n = 99999999999999999L;
// correct answer: 17
int numberOfDigits = String.valueOf(n).length();
// incorrect answer: 18
int wrongNumberOfDigits = (int) (Math.log10(n) + 1);
Logarithm-based solution calculates incorrect number of digits in large integers
Using Java
int nDigits = Math.floor(Math.log10(Math.abs(the_integer))) + 1;
use import java.lang.Math.*; in the beginning
Using C
int nDigits = floor(log10(abs(the_integer))) + 1;
use inclue math.h in the beginning
Since the number of digits in base 10 of an integer is just 1 + truncate(log10(number)), you can do:
public class Test {
public static void main(String[] args) {
final int number = 1234;
final int digits = 1 + (int)Math.floor(Math.log10(number));
System.out.println(digits);
}
}
Edited because my last edit fixed the code example, but not the description.
Another string approach. Short and sweet - for any integer n.
int length = ("" + n).length();
Marian's solution adapted for long type numbers (up to 9,223,372,036,854,775,807), in case someone want's to Copy&Paste it.
In the program I wrote this for numbers up to 10000 were much more probable, so I made a specific branch for them. Anyway it won't make a significative difference.
public static int numberOfDigits (long n) {
// Guessing 4 digit numbers will be more probable.
// They are set in the first branch.
if (n < 10000L) { // from 1 to 4
if (n < 100L) { // 1 or 2
if (n < 10L) {
return 1;
} else {
return 2;
}
} else { // 3 or 4
if (n < 1000L) {
return 3;
} else {
return 4;
}
}
} else { // from 5 a 20 (albeit longs can't have more than 18 or 19)
if (n < 1000000000000L) { // from 5 to 12
if (n < 100000000L) { // from 5 to 8
if (n < 1000000L) { // 5 or 6
if (n < 100000L) {
return 5;
} else {
return 6;
}
} else { // 7 u 8
if (n < 10000000L) {
return 7;
} else {
return 8;
}
}
} else { // from 9 to 12
if (n < 10000000000L) { // 9 or 10
if (n < 1000000000L) {
return 9;
} else {
return 10;
}
} else { // 11 or 12
if (n < 100000000000L) {
return 11;
} else {
return 12;
}
}
}
} else { // from 13 to ... (18 or 20)
if (n < 10000000000000000L) { // from 13 to 16
if (n < 100000000000000L) { // 13 or 14
if (n < 10000000000000L) {
return 13;
} else {
return 14;
}
} else { // 15 or 16
if (n < 1000000000000000L) {
return 15;
} else {
return 16;
}
}
} else { // from 17 to ...¿20?
if (n < 1000000000000000000L) { // 17 or 18
if (n < 100000000000000000L) {
return 17;
} else {
return 18;
}
} else { // 19? Can it be?
// 10000000000000000000L is'nt a valid long.
return 19;
}
}
}
}
}
How about plain old Mathematics? Divide by 10 until you reach 0.
public static int getSize(long number) {
int count = 0;
while (number > 0) {
count += 1;
number = (number / 10);
}
return count;
}
I see people using String libraries or even using the Integer class. Nothing wrong with that but the algorithm for getting the number of digits is not that complicated. I am using a long in this example but it works just as fine with an int.
private static int getLength(long num) {
int count = 1;
while (num >= 10) {
num = num / 10;
count++;
}
return count;
}
Can I try? ;)
based on Dirk's solution
final int digits = number==0?1:(1 + (int)Math.floor(Math.log10(Math.abs(number))));
Marian's Solution, now with Ternary:
public int len(int n){
return (n<100000)?((n<100)?((n<10)?1:2):(n<1000)?3:((n<10000)?4:5)):((n<10000000)?((n<1000000)?6:7):((n<100000000)?8:((n<1000000000)?9:10)));
}
Because we can.
no String API, no utils, no type conversion, just pure java iteration ->
public static int getNumberOfDigits(int input) {
int numOfDigits = 1;
int base = 1;
while (input >= base * 10) {
base = base * 10;
numOfDigits++;
}
return numOfDigits;
}
You can go long for bigger values if you please.
Curious, I tried to benchmark it ...
import org.junit.Test;
import static org.junit.Assert.*;
public class TestStack1306727 {
#Test
public void bench(){
int number=1000;
int a= String.valueOf(number).length();
int b= 1 + (int)Math.floor(Math.log10(number));
assertEquals(a,b);
int i=0;
int s=0;
long startTime = System.currentTimeMillis();
for(i=0, s=0; i< 100000000; i++){
a= String.valueOf(number).length();
s+=a;
}
long stopTime = System.currentTimeMillis();
long runTime = stopTime - startTime;
System.out.println("Run time 1: " + runTime);
System.out.println("s: "+s);
startTime = System.currentTimeMillis();
for(i=0,s=0; i< 100000000; i++){
b= number==0?1:(1 + (int)Math.floor(Math.log10(Math.abs(number))));
s+=b;
}
stopTime = System.currentTimeMillis();
runTime = stopTime - startTime;
System.out.println("Run time 2: " + runTime);
System.out.println("s: "+s);
assertEquals(a,b);
}
}
the results are :
Run time 1: 6765
s: 400000000
Run time 2: 6000
s: 400000000
Now I am left to wonder if my benchmark actually means something but I do get consistent results (variations within a ms) over multiple runs of the benchmark itself ... :) It looks like it's useless to try and optimize this...
edit: following ptomli's comment, I replaced 'number' by 'i' in the code above and got the following results over 5 runs of the bench :
Run time 1: 11500
s: 788888890
Run time 2: 8547
s: 788888890
Run time 1: 11485
s: 788888890
Run time 2: 8547
s: 788888890
Run time 1: 11469
s: 788888890
Run time 2: 8547
s: 788888890
Run time 1: 11500
s: 788888890
Run time 2: 8547
s: 788888890
Run time 1: 11484
s: 788888890
Run time 2: 8547
s: 788888890
With design (based on problem). This is an alternate of divide-and-conquer. We'll first define an enum (considering it's only for an unsigned int).
public enum IntegerLength {
One((byte)1,10),
Two((byte)2,100),
Three((byte)3,1000),
Four((byte)4,10000),
Five((byte)5,100000),
Six((byte)6,1000000),
Seven((byte)7,10000000),
Eight((byte)8,100000000),
Nine((byte)9,1000000000);
byte length;
int value;
IntegerLength(byte len,int value) {
this.length = len;
this.value = value;
}
public byte getLenght() {
return length;
}
public int getValue() {
return value;
}
}
Now we'll define a class that goes through the values of the enum and compare and return the appropriate length.
public class IntegerLenght {
public static byte calculateIntLenght(int num) {
for(IntegerLength v : IntegerLength.values()) {
if(num < v.getValue()){
return v.getLenght();
}
}
return 0;
}
}
The run time of this solution is the same as the divide-and-conquer approach.
What about this recursive method?
private static int length = 0;
public static int length(int n) {
length++;
if((n / 10) < 10) {
length++;
} else {
length(n / 10);
}
return length;
}
simple solution:
public class long_length {
long x,l=1,n;
for (n=10;n<x;n*=10){
if (x/n!=0){
l++;
}
}
System.out.print(l);
}
A really simple solution:
public int numLength(int n) {
for (int length = 1; n % Math.pow(10, length) != n; length++) {}
return length;
}
Or instead the length you can check if the number is larger or smaller then the desired number.
public void createCard(int cardNumber, int cardStatus, int customerId) throws SQLException {
if(cardDao.checkIfCardExists(cardNumber) == false) {
if(cardDao.createCard(cardNumber, cardStatus, customerId) == true) {
System.out.println("Card created successfully");
} else {
}
} else {
System.out.println("Card already exists, try with another Card Number");
do {
System.out.println("Enter your new Card Number: ");
scan = new Scanner(System.in);
int inputCardNumber = scan.nextInt();
cardNumber = inputCardNumber;
} while(cardNumber < 95000000);
cardDao.createCard(cardNumber, cardStatus, customerId);
}
}
}
I haven't seen a multiplication-based solution yet. Logarithm, divison, and string-based solutions will become rather unwieldy against millions of test cases, so here's one for ints:
/**
* Returns the number of digits needed to represents an {#code int} value in
* the given radix, disregarding any sign.
*/
public static int len(int n, int radix) {
radixCheck(radix);
// if you want to establish some limitation other than radix > 2
n = Math.abs(n);
int len = 1;
long min = radix - 1;
while (n > min) {
n -= min;
min *= radix;
len++;
}
return len;
}
In base 10, this works because n is essentially being compared to 9, 99, 999... as min is 9, 90, 900... and n is being subtracted by 9, 90, 900...
Unfortunately, this is not portable to long just by replacing every instance of int due to overflow. On the other hand, it just so happens it will work for bases 2 and 10 (but badly fails for most of the other bases). You'll need a lookup table for the overflow points (or a division test... ew)
/**
* For radices 2 &le r &le Character.MAX_VALUE (36)
*/
private static long[] overflowpt = {-1, -1, 4611686018427387904L,
8105110306037952534L, 3458764513820540928L, 5960464477539062500L,
3948651115268014080L, 3351275184499704042L, 8070450532247928832L,
1200757082375992968L, 9000000000000000000L, 5054470284992937710L,
2033726847845400576L, 7984999310198158092L, 2022385242251558912L,
6130514465332031250L, 1080863910568919040L, 2694045224950414864L,
6371827248895377408L, 756953702320627062L, 1556480000000000000L,
3089447554782389220L, 5939011215544737792L, 482121737504447062L,
839967991029301248L, 1430511474609375000L, 2385723916542054400L,
3902460517721977146L, 6269893157408735232L, 341614273439763212L,
513726300000000000L, 762254306892144930L, 1116892707587883008L,
1617347408439258144L, 2316231840055068672L, 3282671350683593750L,
4606759634479349760L};
public static int len(long n, int radix) {
radixCheck(radix);
n = abs(n);
int len = 1;
long min = radix - 1;
while (n > min) {
len++;
if (min == overflowpt[radix]) break;
n -= min;
min *= radix;
}
return len;
}
One wants to do this mostly because he/she wants to "present" it, which mostly mean it finally needs to be "toString-ed" (or transformed in another way) explicitly or implicitly anyway; before it can be presented (printed for example). If that is the case then just try to make the necessary "toString" explicit and count the bits.
We can achieve this using a recursive loop
public static int digitCount(int numberInput, int i) {
while (numberInput > 0) {
i++;
numberInput = numberInput / 10;
digitCount(numberInput, i);
}
return i;
}
public static void printString() {
int numberInput = 1234567;
int digitCount = digitCount(numberInput, 0);
System.out.println("Count of digit in ["+numberInput+"] is ["+digitCount+"]");
}
I wrote this function after looking Integer.java source code.
private static int stringSize(int x) {
final int[] sizeTable = {9, 99, 999, 9_999, 99_999, 999_999, 9_999_999,
99_999_999, 999_999_999, Integer.MAX_VALUE};
for (int i = 0; ; ++i) {
if (x <= sizeTable[i]) {
return i + 1;
}
}
}
One of the efficient ways to count the number of digits in an int variable would be to define a method digitsCounter with a required number of conditional statements.
The approach is simple, we will be checking for each range in which a n digit number can lie:
0 : 9 are Single digit numbers
10 : 99 are Double digit numbers
100 : 999 are Triple digit numbers and so on...
static int digitsCounter(int N)
{ // N = Math.abs(N); // if `N` is -ve
if (0 <= N && N <= 9) return 1;
if (10 <= N && N <= 99) return 2;
if (100 <= N && N <= 999) return 3;
if (1000 <= N && N <= 9999) return 4;
if (10000 <= N && N <= 99999) return 5;
if (100000 <= N && N <= 999999) return 6;
if (1000000 <= N && N <= 9999999) return 7;
if (10000000 <= N && N <= 99999999) return 8;
if (100000000 <= N && N <= 999999999) return 9;
return 10;
}
A cleaner way to do this is to remove the check for the lower limits as it won't be required if we proceed in a sequential manner.
static int digitsCounter(int N)
{
N = N < 0 ? -N : N;
if (N <= 9) return 1;
if (N <= 99) return 2;
if (N <= 999) return 3;
if (N <= 9999) return 4;
if (N <= 99999) return 5;
if (N <= 999999) return 6;
if (N <= 9999999) return 7;
if (N <= 99999999) return 8;
if (N <= 999999999) return 9;
return 10; // Max possible digits in an 'int'
}
Ideally, an integer divided by 10 multiple times will return the number of digits as long as the integer is not zero. As such a simple method to do so can be created as below.
public static int getNumberOfDigits(int number) {
int numberOfDigits = 0;
while(number != 0) {
number /= 10;
numberOfDigits++;
}
return numberOfDigits;
}
It depends on what you mean by "neat". I think the following code is fairly neat, and it runs fast.
It is based on Marian's answer, extended to work with all long values and rendered using the ? : operator.
private static long[] DIGITS = { 1l,
10l,
100l,
1000l,
10000l,
100000l,
1000000l,
10000000l,
100000000l,
1000000000l,
10000000000l,
100000000000l,
1000000000000l,
10000000000000l,
100000000000000l,
1000000000000000l,
10000000000000000l,
100000000000000000l,
1000000000000000000l };
public static int numberOfDigits(final long n)
{
return n == Long.MIN_VALUE ? 19 : n < 0l ? numberOfDigits(-n) :
n < DIGITS[8] ? // 1-8
n < DIGITS[4] ? // 1-4
n < DIGITS[2] ? // 1-2
n < DIGITS[1] ? 1 : 2 : // 1-2
n < DIGITS[3] ? 3 : 4 : // 3-4
n < DIGITS[6] ? // 5-8
n < DIGITS[5] ? 5 : 6 : // 5-6
n < DIGITS[7] ? 7 : 8 : // 7-8
n < DIGITS[16] ? // 9-16
n < DIGITS[12] ? // 9-12
n < DIGITS[10] ? // 9-10
n < DIGITS[9] ? 9 : 10 : // 9-10
n < DIGITS[11] ? 11 : 12 : // 11-12
n < DIGITS[14] ? // 13-16
n < DIGITS[13] ? 13 : 14 : // 13-14
n < DIGITS[15] ? 15 : 16 : // 15-16
n < DIGITS[17] ? 17 : // 17-19
n < DIGITS[18] ? 18 :
19;
}
Here is what such solution looks from the JDK developers. This is JDK 17 (class Long):
/**
* Returns the string representation size for a given long value.
*
* #param x long value
* #return string size
*
* #implNote There are other ways to compute this: e.g. binary search,
* but values are biased heavily towards zero, and therefore linear search
* wins. The iteration results are also routinely inlined in the generated
* code after loop unrolling.
*/
static int stringSize(long x) {
int d = 1;
if (x >= 0) {
d = 0;
x = -x;
}
long p = -10;
for (int i = 1; i < 19; i++) {
if (x > p)
return i + d;
p = 10 * p;
}
return 19 + d;
}
Note that the method takes into account a minus sign, if necessary.
Unfortunately the method is not exposed.
In terms of performance you can see from the comments that the JDK developer has at least given this some thought compared to alternatives. I would guess that
a divide-and-conquer method skewed toward lower numbers would perform slightly
better, because the CPU can do integer comparisons a bit faster than integer
multiplications. But the difference may so small that it is not measurable.
In any case, I wish this method had been exposed in the JDK so that people would not start rolling their own method.
Here's a really simple method I made that works for any number:
public static int numberLength(int userNumber) {
int numberCounter = 10;
boolean condition = true;
int digitLength = 1;
while (condition) {
int numberRatio = userNumber / numberCounter;
if (numberRatio < 1) {
condition = false;
} else {
digitLength++;
numberCounter *= 10;
}
}
return digitLength;
}
The way it works is with the number counter variable is that 10 = 1 digit space. For example .1 = 1 tenth => 1 digit space. Therefore if you have int number = 103342; you'll get 6, because that's the equivalent of .000001 spaces back. Also, does anyone have a better variable name for numberCounter? I can't think of anything better.
Edit: Just thought of a better explanation. Essentially what this while loop is doing is making it so you divide your number by 10, until it's less than one. Essentially, when you divide something by 10 you're moving it back one number space, so you simply divide it by 10 until you reach <1 for the amount of digits in your number.
Here's another version that can count the amount of numbers in a decimal:
public static int repeatingLength(double decimalNumber) {
int numberCounter = 1;
boolean condition = true;
int digitLength = 1;
while (condition) {
double numberRatio = decimalNumber * numberCounter;
if ((numberRatio - Math.round(numberRatio)) < 0.0000001) {
condition = false;
} else {
digitLength++;
numberCounter *= 10;
}
}
return digitLength - 1;
}

Categories