php power of number mod number not work - php

why this function return 0 ?
public function encrypt(){
return (pow(123,17)%3233);
}

What happens here is you get an integer overflow. Your number is way bigger than PHP_INT_MAX. So to still be able to do this calculation you can use the BC math library .
So just use bcpowmod(), e.g.
echo bcpowmod(123, 17, 3233);

Related

Why strlen doesn't work in a paticular digit

I made this function. It seemed it's working but when it comes to 20 digits number, the return value was 19. I'm wondering why this problem happen..
My function
function sumDigits($n) {
return strlen($n);
}
echo sumDigits(100); //3
echo sumDigits(1000); //4
echo sumDigits(12345); //5
echo sumDigits(1000000000); //10
echo sumDigits(145874589632); //12
echo sumDigits(0); //1
echo sumDigits(12345698745254856320); //19 <-- Why not 20?
Can you please somebody explain for me?
Thank you so much.
First, I would point out that the name of your function is misleading, as you are not really summing the values of the digits, but are counting the digits. So I would call your function countDigits instead of sumDigits.
The reason why it doesn't work for large numbers, is that the string representation will switch to scientific notation, so you're actually getting the length of "1.2345698745255E+19" not of "12345698745254856320"
If you are only interested in integers, you will get better results with the logarithm:
function countDigits($n) {
return ceil(log10($n));
}
For numbers that have decimals, there is no good solution, since the precision of 64-bit floating pointing point numbers is limited to about 16 significant digits, so even if you provide more digits, the trailing decimals will be dropped -- this has nothing to do with your function, but with the precision of the number itself. For instance, you'll find that these two literals are equal:
if (1.123456789123456789123456789 == 1.12345678912345678) echo "equal";
Because you function parameter is an integer, exceeding the limit.
If you dump it, it actually shows the following:
1.2345698745255E+19 - which is 19 letters.
If you would do the following, it will return 20 - mind the quotes, which declares the input as string.
echo sumDigits("12345698745254856320"); //19 <-- Why not 20? -> now will be 20
As per documentation, strlen() expects a string so a cast happens. With default settings you get 1.2345698745255E+19:
var_dump((string)12345698745254856320);
string(19) "1.2345698745255E+19"
The root issue is that PHP converts your integer literal to float because it exceeds PHP_INT_MAX so it cannot be represented as integer:
var_dump(12345698745254856320, PHP_INT_MAX);
In 64-bit PHP:
float(1.2345698745254857E+19)
int(9223372036854775807)
You could change display settings to avoid E notation but you've already lost precision at this point.
Computer languages that store integers as a fixed amount of bytes do not allow arbitrary precision. Your best chance is to switch to strings:
var_dump('12345698745254856320', strlen('12345698745254856320'));
string(20) "12345698745254856320"
int(20)
... and optionally use an arbitrary precision library such as BCMath or GMP if you need actual maths.
It's also important to consider that this kind of issues is sometimes a symptom that your input data is not really meant to be an integer but just a very long digit-only string.

In PHP number with 19 digit changes in to exponential number

In PHP i have define a variable with 19 digit long number and then print it. But it changes into exponential NUmber which is not acceptable in API Use. I need it as NUMBER. Here is an example of Problem.
$a = 1435483000000072013;
echo $a;
adn it returns 1.4354830000001E+18
Also, I have tried following function but it return wrong number
function output($x) {
$f = sprintf('%0.08f', $x);
$f = rtrim($f,'0');
$f = rtrim($f,'.');
return $f;
}
echo output(1435483000000072013);
this returns me 1435483000000071936 Number changes
So what is solution for this??
Champ, PHP doesn't have strictly typed variables, but it still has to decide whether your number is an int, a float or a double when it stores the information. And your number is larger than INT_MAX, so it's not going to fit into an integer format. That means the system has to bump it up to at least a float, which is where you're getting the exponential format from.
See NoGray's solution for how to fix it. Your number is still being stored, it's just being represented differently because your number is too big.
You can use number_format with an empty string for the thousands separator
e.g.
$a = 1435483000000072013;
echo number_format($a, 0, '.', '');
$a = 1.435483000000072013;
printf("%.18f",$a);

Power function in php to calculate 17^2147482999

I am trying to make a power function to calculate the power of 17^2147482999.
I tried this code:
function ipow($a, $b) {
if ($b<0) {
echo "B must be a positive integer";
}
if ($b==0) return 1;
if ($a==0) return 0;
if ($b%2==0) {
return ipow($a*$a, $b/2);
} else if ($b%2==1) {
return $a*ipow($a*$a,$b/2);
}
return 0;
}
The function call:
echo ipow($a, $b);
The error:
Fatal error: Maximum function nesting level of '100' reached, aborting! in C:\wamp\www\spoj\LASTDIG.php on line 23
Is there any other way to calculate the power for such big values? The inbuilt pow() function is giving an INF output.
UPDATE
If it seems impossible to get the whole answer, is it possible to extract atleast the last 5-10 digits of the answer by some mathematical approach?
You cannot do that with plain PHP arithemtic operations. That's way out of range for integers, even on 64-bit systems.
You need to use the bcmath extension and the bcpow function. (If that doesn't work maybe even gmp.)
print bcpow(17, 2147482999);
You may use bcpowmod function like this:
<?php echo bcpowmod(17,2147482999,10000000000); ?>
the result is 8849802353 which means, 17^2147482999 mod 10000000000 or, the last 10 digits of 17^2147482999 is 8849802353.
The resulting value is something in the order of 1e+2642368139, a lot more than can fit in most libraries. If you want some approximation, you can use some logarithmic logic:
17^2147482999 = 10^(log(17^2147482999))
= 10^(2147482999 * log(17))
= 10^(2147482999 * 1.23045)
= 10^(2642368139.79773)
= 10^2642368139 * 10^0.79773
= 6.27669e+2642368139
GNU Multiple Precision and namely gmp_pow may be what you are looking for.
I suggest you look into BigInteger, the constant PHP_INT_MAX will tell you how big an integer your platform can handle. On 64 bit this returns 9223372036854775807, wich is far from for your result in decimal notation.
Try to change the algorithm and instead of working with numbers (as the data type) ... work with plain strings. It will take a lot of time to compute it but it will be achievable :)

Factorial of 170+

everytime I try to get the factorial of 171, I get INF. 170 works fine. Is it possible to get the factorial of 171+ in a script? How?
My function:
function factorial($n) {
if ($n == 0) return 1;
return $n * factorial($n - 1);
}
If you deal with very large numbers, you'll need to use an extension that allows you to do that.
There's BCMath ( http://www.php.net/manual/en/book.bc.php) , and GMP ( http://www.php.net/manual/en/book.gmp.php ).
You'll have to use BC Math or GNU MP extension. PHP doesn't provide any tools for high-values or high-precision operations OOTB.
echo "1241018070217667823424840524103103992616605577501693185388951803611996075221691752992751978120487585576464959501670387052809889858690710767331242032218484364310473577889968548278290754541561964852153468318044293239598173696899657235903947616152278558180061176365108428800000000000000000000000000000000000000000"
really though, your function is fine. I think PHP lacks that kind of precision. I got the value (it is correct btw) in python
You are probably getting a value that exceeds the maximum double precision float in a 32-bit machine (~10^308). 170! factorial is ~7.25741562 × 10^307 which is just under that, however, 171! is larger. Your best bet is to use one of the libraries EboMike or Crozin recommends in their answers.
For large n, you can compute n! very quickly with little error using Stirling's approximation. Take a look at this post; it has an analysis of the function and some sample code:
http://threebrothers.org/brendan/blog/stirlings-approximation-formula-clojure/
It's a bigger number than you can hold using 32-bits. If you run the same code on a 64-bit computer then it should work.

Is there something that's larger than any numbers in PHP?

I need to simulate a ∞ in PHP.
So that min(∞,$number) is always $number.
I suppose that, for integers, you could use PHP_INT_MAX , the following code :
var_dump(PHP_INT_MAX);
Gives this output, on my machine :
int 2147483647
But you have to be careful ; see Integer overflow (quoting) :
If PHP encounters a number beyond the
bounds of the integer type, it will
be interpreted as a float instead.
Also, an operation which results in a
number beyond the bounds of the
integer type will return a float
instead.
And, from the Floating point numbers documentation page :
The size of a float is
platform-dependent, although a maximum
of ~1.8e308 with a precision of
roughly 14 decimal digits is a common
value (the 64 bit IEEE format).
Considering the integer overflow, and depending on your case, using this kind of value might be a better (?) solution...
Use the constant PHP_INT_MAX.
http://php.net/manual/en/language.types.integer.php
You could potentially use the PHP_INT_MAX constant (click for PHP manual docs).
However, you may want to think about whether you really need to use it - it seems like a bit of an odd request.
PHP actually has a predefined constant for "infinity": INF. This isn't true infinity, but is essentially the largest float value possible. On 64-bit systems, the largest float is roughly equal to 1.8e308, so this is considered to be equal to infinity.
$inf = INF;
var_dump(min($inf,PHP_INT_MAX)); // outputs int(9223372036854775807)
var_dump(min($inf,1.79e308)); // outputs float(1.79E+308)
var_dump(min($inf,1.799e308)); // outputs float(INF)
var_dump(min($inf,1.8e308)); // outputs float(INF)
var_dump($inf === 1.8e308); // outputs bool(true)
Note, any number with a value larger than the maximum float value will be cast to INF. So therefore if we do, var_dump($inf === 1e50000);, this will also output true even though the maximum float is less than this.
I suppose, assuming this is an integer, you could use PHP_INT_MAX constant.
min($number, $number + 1) ??
In Perl you can use
$INF = 9**9E9;
which is larger than any value you can store in IEEE floating point numbers. And that really works as intended: any non-infinite number will be smaller than $INF:
$N < $INF
is true for any "normal" number $N.
Maybe you use it in PHP too?
min($number,$number) is always $number (also true for max() of course).
If your only concern is comparison function then yes, you can use array(), it will be always larger then any number
like
echo min(array(), 9999999999999999);
or
if (array() > 9999999999999999) {
echo 'array won';
} else {
echo 'number won';
}

Categories