I want to count the nth positive root of p for example we have n=2 and p=16 the answer is 4 because
4^2 = 16. I want to do this for huge numbers (1 <= n <= 200, 1 <= p < 10^101). I don't know how should I do it as fast as possible.
Example:
n=2 p=16 Answer 4
n=7 p=4357186184021382204544 Answer 1234
There are arbitrary precision math packages out there, if you have to come up with your own algorithm.
But you might try this: Get p into a double any way you can (a double can handle 10^101.) Then use math.h::pow(p, 1.0/n), and that answer will be close to the right integer (round it?). But this will fail if p is more than 15 digits, and n is too small, e.g., p = 10^100, n=2 gives a 50 digit answer, which is too big an integer for double to represent exactly.
Get 101 digit p into double: cut the number (string) into 10 digit chunks, multiply each by 10 to the appropriate power, and add them up.
Try Newton's method as described here:
http://en.wikipedia.org/wiki/Nth_root_algorithm
Take log of p, divide by n, and take the anti-log:
nthRoot(p, n) := Math.Power(10, Math.Log(p) / n)
Not sure whether you're specifically dealing with integers or what but that is the psuedo-code for it.
Related
I'm writing a program which must take in an integer, N, in range 3<=N<=10^18.
This is one of the operations I have to perform with N.
final=((0.5*(pow(2,0.5))*(pow((pow(((N/2)-0.5),2)+pow((N/2)-0.5,2)),0.5)))-0.5)*4;
N is such that final is guaranteed to contain an integer.
The problem is that I can't store N in a float type as it is too large. If I store it in long long int, the answer is wrong(I think its because the intermediate value of N / 2 is then rounded off).
The correct answer is
final = 2 * abs(N-1) - 2;
This can be verified, by removing the unnecessary parenthesis, regrouping same terms, distributing multiplication by constants, and using the following identities:
square root of squared is absolute value: pow(pow(x,2),0.5) = abs(x)
pow(k*x,0.5) = pow(k,0.5)*pow(x,0.5)
k*abs(x+y) = abs(k*x + k*y)
This is almost the same than the accepted answer. But the other answer is correct only for any N >= 1. It is wrong as soon as N-1<0, so in the range of the possible N values allowed by your question, for 0 <= N < 1
You can verify this with this online demo
Edit: following your edit of the question that changes the range and therewith exclude the problematic values, the accepted answer will do. I leave my answer here for the records, and for the sake of the maths ;-)
This formula looks intimidating, but can be simplified (if N > 1) to
final = 4 * (N / 2 - 1)
using the identity: (xa)1/a = x.
If N / 2 is supposed to be a floating-point division, not an integer one, the answer is
final = 2 * (N - 2)
The program asks the user for the number of times to flip a coin (n; the number of trials).
A success is considered a heads.
Flawlessly, the program creates a random number between 0 and 1. 0's are considered heads and success.
Then, the program is supposed to output the expected values of getting x amount of heads. For example if the coin was flipped 4 times, what are the following probabilities using the formula
nCk * p^k * (1-p)^(n-k)
Expected 0 heads with n flips: xxx
Expected 1 heads with n flips: xxx
...
Expected n heads with n flips: xxx
When doing this with "larger" numbers, the numbers come out to weird values. It happens if 15 or twenty are put into the input. I have been getting 0's and negative values for the value that should be xxx.
Debugging, I have noticed that the nCk has come out to be negative and not correct towards the upper values and beleive this is the issue. I use this formula for my combination:
double combo = fact(n)/fact(r)/fact(n-r);
here is the psuedocode for my fact function:
long fact(int x)
{
int e; // local counter
factor = 1;
for (e = x; e != 0; e--)
{
factor = factor * e;
}
return factor;
}
Any thoughts? My guess is my factorial or combo functions are exceeding the max values or something.
You haven't mentioned how is factor declared. I think you are getting integer overflows. I suggest you use double. That is because since you are calculating expected values and probabilities, you shouldn't be concerned much about precision.
Try changing your fact function to.
double fact(double x)
{
int e; // local counter
double factor = 1;
for (e = x; e != 0; e--)
{
factor = factor * e;
}
return factor;
}
EDIT:
Also to calculate nCk, you need not calculate factorials 3 times. You can simply calculate this value in the following way.
if k > n/2, k = n-k.
n(n-1)(n-2)...(n-k+1)
nCk = -----------------------
factorial(k)
You're exceeding the maximum value of a long. Factorial grows so quickly that you need the right type of number--what type that is will depend on what values you need.
Long is an signed integer, and as soon as you pass 2^31, the value will become negative (it's using 2's complement math).
Using an unsigned long will buy you a little time (one more bit), but for factorial, it's probably not worth it. If your compiler supports long long, then try an "unsigned long long". That will (usually, depends on compiler and CPU) double the number of bits you're using.
You can also try switching to use double. The problem you'll face there is that you'll lose accuracy as the numbers increase. A double is a floating point number, so you'll have a fixed number of significant digits. If your end result is an approximation, this may work okay, but if you need exact values, it won't work.
If none of these solutions will work for you, you may need to resort to using an "infinite precision" math package, which you should be able to search for. You didn't say if you were using C or C++; this is going to be a lot more pleasant with C++ as it will provide a class that acts like a number and that would use standard arithmetic operators.
Where I need help...
What I want to do now is translate this solution, which calculates the mantissaof a number to c++:
n^m = exp10(m log10(n)) = exp(q (m log(n)/q)) where q = log(10)
Finding the first n digits from the result can be done like this:
"the first K digits of exp10(x) = the first K digits of exp10(frac(x))
where frac(x) = the fractional part of x = x - floor(x)."
My attempts (sparked by the math and this code) failed...:
u l l function getPrefix(long double pow /*exponent*/, long double length /*length of prefix*/)
{
long double dummy; //unused but necessary for modf
long double q = log(10);
u l l temp = floor(pow(10.0, exp(q * modf( (pow * log(2)/q), &dummy) + length - 1));
return temp;
}
If anyone out there can correctly implement this solution, I need your help!!
EDIT
Example output from my attempts:
n: 2
m: 0
n^m: 1
Calculated mantissa: 1.16334
n: 2
m: 1
n^m: 2
Calculated mantissa: 2.32667
n: 2
m: 2
n^m: 4
Calculated mantissa: 4.65335
n: 2
m: 98
n^m: 3.16913e+29
Calculated mantissa: 8.0022
n: 2
m: 99
n^m: 6.33825e+29
Calculated mantissa: 2.16596
I'd avoid pow for this. It's notoriously hard to implement correctly. There are lots of SO questions where people got burned by a bad pow implementation in their standard library.
You can also save yourself a good deal of pain by working in the natural base instead of base 10. You'll get code that looks like this:
long double foo = m * logl(n);
foo = fmodl(foo, logl(10.0)) + some_epsilon;
sprintf(some_string, "%.9Lf", expl(foo));
/* boring string parsing code here */
to compute the appropriate analogue of m log(n). Notice that the largest m * logl(n) that can arise is just a little bigger than 2e10. When you divide that by 264 and round up to the nearest power of two, you see that an ulp of foo is 2-29 at worst. This means, in particular, that you cannot get more than 8 digits out of this method using long doubles, even with a perfect implementation.
some_epsilon will be the smallest long double that makes expl(foo) always exceed the mathematically correct result; I haven't computed it exactly, but it should be on the order of 1e-9.
In light of the precision difficulties here, I might suggest using a library like MPFR instead of long doubles. You may also be able to get something to work using a double double trick and quad-precision exp, log, and fmod.
Is there any fast way in C (below 1 sec) to find the number of perfect squares between two numbers.
For ex. for 1 <-> 10 we have 2 perfect squares 4 and 9. But what about between 1<->2^60 or some other bigger number.
This is slow
while(i*i<=n)
{
sum+=i==((long long)(sqrt(i*i)));
i++;
}
where n is lets say 2^60 and we start with i=2.
x = (int)sqrt(n2) - (int)sqrt(n1);
Its trivial. Assume you have two endpoints, a & b, with a < b.
What is the next perfect square after a? Hint, what is sqrt(a)? What would rounding up do?
What is the largest perfect square that does not exceed b? Hint, what is sqrt(b)? Again, how would rounding help here?
Once you know those two numbers, counting the number of perfect squares seems truly trivial.
By the way, be careful. Even the sqrt of 2^60 is a big number, although it will fit into a double. The problem is that 2^60 is too large to fit into a standard double, since it exceeds 2^53. So beware precision issues.
Don't iterate. The equation:
floor(sqrt(b)) - ceil(sqrt(a)) + 1
gives the number of perfect squares in the interval from a up to b inclusive.
https://en.wikipedia.org/wiki/Intermediate_value_theorem
if(n1 is a perfect square)
x=(int)sqrt(n2)-(int)sqrt(n1)+1;
else
x=(int)sqrt(n2)-(int)sqrt(n1);
Language-agnostic formula to get the number of perfect squares in range [a, b] inclusive, as long as the basic math function sqrt, ceil and floor are provided by the standard lib.
cnt = int(floor(sqrt(b))) - int(ceil(sqrt(a))) + 1
From Cay Horstmann's "C++ For Everyone"
Chapter 4: Loops
Write a program that adds up the sum of all odd digits of n. (For example, if n is 32677, the sum would be 3 + 7 + 7 = 17)
I don't know how to make the computer "see" the numbers like separate them
n % 10 gets the value of the one's digit. You can figure it out from there right?
Here's a hint. C++ has the modulus operator %. It will produce the remainder when two numbers are divided together. So if I wanted to know the last digit in a number which was greater than 10 I would modulus 10 and get the result
int lastDigit = number % 10;
The last digit of a base-10 integer i is equal to i % 10. (For reference, % is the modulus operator; it basically returns the remainder from dividing the left number by the right.)
So, now you have the last digit. Once you do, add it to a running total you're keeping, divide i by 10 (effectively shifting the digits down by one place), or in your case 100 (two places), and start back at the beginning. Repeat until i == 0.
People here rather not provide you with the answer to your exercise, but to provide you with hints so that you can find the answer on your own and more importantly understand it.
To start, the following arithmetic operations will help you:
loop:
right_most_digit = n % 10
n = n / 10
end_loop