Very big numbers make bcpowmod overflow - php

I need to raise 8 to the power of 17 in PHP. I have checked this to be 2251799813685248 on my PC's calculator, but both the pow() and bcpowmod() functions seem to overflow; pow() goes into scientific notation, and echoing the results from bcpowmod(), even with a high third parameter gives me a blank screen. Is there any other way I could perform this calculation?

You can try with gmp_pow
gmp_pow("8", 17);
With h2ooooooo suggestion - to get result use:
gmp_strval(gmp_pow("8", 17));
Also bcpow works well for me
bcpow("8", "17")

Use pow(). The "scientific notation" you are talking about is just a notation and you can format it later.
echo number_format(pow(8,17), 0, '', '');
http://php.net/number-format
Beside this I couldn't reproduce the "scientific-notation"-behaviour for the given values
http://codepad.viper-7.com/AwM3CS (Uses bigger values to enforce the scientific notation)

Related

PHP is converting decimal to exponential value [duplicate]

In PHP I have the following code:
<?PHP
$var = .000021;
echo $var;
?>
the output is 2.1E-5 !
Why? it should print .000021
Use number_format() to get what you're after:
print number_format($var, 5);
Also check sprintf()
2.1E-5 is the same number as 0.000021. That's how it prints numbers below 0.001. Use printf() if you want it in a particular format.
Edit If you're not familiar with the 2.1E-5 syntax, you should know it is shorthand for 2.1×10-5. It is how most programming languages represent numbers in scientific notation.
Use number_format or sprintf if you want to see the number as you expect.
echo sprintf('%f', $var);
echo number_format($var, 6);
To show a number up to 8 decimal spaces, without extra zeroes to the right (as number_format does, which can be annoying), use this:
echo rtrim(rtrim(sprintf('%.8F', $var), '0'), ".");
In general, a number is a number, not a string, and this means that any programming language treats a number as a number. Thus, the number by itself doesn't imply any specific format (like using .000021 instead of 2.1e-5). This is nothing different to displaying a number with leading zeros (like 0.000021) or aligning lists of numbers. This is a general issue you'll find in any programming language: if you want a specific format you need to specify it, using the format functions of your programming language.
Unless you specify the number as string and convert it to a real number when needed, of course. Some languages can do this implicitly.
The previous answers responded to OP question, but none offered the code to do it.
Use this function to format any number with E- format.
function format_amount_with_no_e($amount) {
$amount = (string)$amount; // cast the number in string
$pos = stripos($amount, 'E-'); // get the E- position
$there_is_e = $pos !== false; // E- is found
if ($there_is_e) {
$decimals = intval(substr($amount, $pos + 2, strlen($amount))); // extract the decimals
$amount = number_format($amount, $decimals, '.', ','); // format the number without E-
}
return $amount;
}
Please note the function will always return a string.
Programming languages have different methods for storing numbers in memory. This is determined by the type of number that is being used. In your case, you have a floating point number (a fraction) that is to large to be stored as a fixed point number ( fractions are stored in this manner depending on their size).
This is a very important feature especially when working with very large or very small numbers. For instance, NASA or spaceX uses special storage methods for its calculations to ensure that the rockets the re-enter earths orbit land where they should.
Also, different storage methods take up different amounts of memory. However, the solution provided above should work. Just remember round off errors might occur with very big or small numbers.

PHP Long string. Output it all

So I got a really long string, made by a calculator.
$string='483451102828322427131269442894636268716773727170';
$result=(8902543901+$string)*($string/93.189)/($string)+55643907015.57895461;
echo $result;
This outputs 5.1878558931668E+45
So now my question is. How can I output the whole string, without that nasty E+45?
PHP on a 64 bit machine can only accurately calculate number up until 9223372036854775807. As soon as you calculate with numbers higher than that, php will switch to floats which may loose some of it's precision, especially when you use divisions.
There's an extension for php that will allow you to make calculations based on string, called BCMath.
Example:
$string = '483451102828322427131269442894636268716773727170';
$result = bcadd($string, 8902543901);
echo $result;
bcadd() is for additions, bcdiv() for divisions and bcmul() for multiplying.
You can't print exact value because you are using calculation, so this $string becomes a number (float in this case) and all numbers have limited precision.
If you want to do operations on big numbers you should use BCMath
However if you want to display it without scientific notation you can do it using:
echo sprintf("%f",$result);
or
echo sprintf("%.0f",$result);
if you want to omit decimal part

Comparing different strings in PHP with == returns true

I was just debugging a script and found that an if-statement wasn't working the way I expected it to.
var_dump("6064365413078728979" == "6064365413078728452");
die();
The code above will result in the following:
bool(true)
With the === operator it works as expected. Anyone got any ideas why?
I'm using PHP Version 5.3.13 with a wamp installation on a x64 windows machine.
PHP has loose type comparison behavior, so your numerical strings are getting converted to integer types before == non strict comparison, and the conversion result is overflowing.
That is the principal reason to use === when it's possible.
Take a look at this page for further details on type juggling.
<?php
$a=6064365413078728979;
$b=6064365413078728452;
echo $a."<br>".$b;
//var_dump( $a==$b );
die();
?>
When you run that, then on your machine that might be exceeding limit for a number and that is a numeric comparison taking place. Try the script above and see value for $a will probably be different than the value you gave.
That is why when both are compared numerically they are equal. Hence use === as suggested by others
Edit: Explanation based upon #Axel's Advice.
PHP Manual explains
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).
And this website is offering and explanation on the Overflow phenomenon and a small php code to test your system's integer and float range. Getting to know the limit on your servers will most probably explain it best why the offerflow occured

Floor function not working

Given the following cod:
$number = 1050.55;
var_dump($number - floor($number));
Why does the above code returns the following result?
float(0.54999999999995)
I want a fixed value like 0.55 in this case. Can you help me please?
Floating point operations are not precise and the remainder errors are common.
If you know, what is your desired precission (eg. two digits after the dot), you can use round() function on the result.
In this case this will be:
$number = 1050.55;
var_dump(round($number - floor($number), 2));
For most floats, binary can only approximately represent the correct number. The rule is to perform floor(), ceil() or fmod() last in a series of calculations. At least only do integer math after you use them. If you cast an int to a float, as in your code, then floor() is not going to behave has you expect.
Use printf() when printing floats. Its conversion routines usually do a much better job and give you the answer you expect when truncating floats.
EDIT: Or, to be more exact, printf() works on the decimal character representation of the number when deciding where to truncate so you don't get any weird, unspecified, binary/decimal conversion artifacts.
See this question. While that is about java and you're asking about PHP the math is the same.

Why is PHP printing my number in scientific notation, when I specified it as .000021?

In PHP I have the following code:
<?PHP
$var = .000021;
echo $var;
?>
the output is 2.1E-5 !
Why? it should print .000021
Use number_format() to get what you're after:
print number_format($var, 5);
Also check sprintf()
2.1E-5 is the same number as 0.000021. That's how it prints numbers below 0.001. Use printf() if you want it in a particular format.
Edit If you're not familiar with the 2.1E-5 syntax, you should know it is shorthand for 2.1×10-5. It is how most programming languages represent numbers in scientific notation.
Use number_format or sprintf if you want to see the number as you expect.
echo sprintf('%f', $var);
echo number_format($var, 6);
To show a number up to 8 decimal spaces, without extra zeroes to the right (as number_format does, which can be annoying), use this:
echo rtrim(rtrim(sprintf('%.8F', $var), '0'), ".");
In general, a number is a number, not a string, and this means that any programming language treats a number as a number. Thus, the number by itself doesn't imply any specific format (like using .000021 instead of 2.1e-5). This is nothing different to displaying a number with leading zeros (like 0.000021) or aligning lists of numbers. This is a general issue you'll find in any programming language: if you want a specific format you need to specify it, using the format functions of your programming language.
Unless you specify the number as string and convert it to a real number when needed, of course. Some languages can do this implicitly.
The previous answers responded to OP question, but none offered the code to do it.
Use this function to format any number with E- format.
function format_amount_with_no_e($amount) {
$amount = (string)$amount; // cast the number in string
$pos = stripos($amount, 'E-'); // get the E- position
$there_is_e = $pos !== false; // E- is found
if ($there_is_e) {
$decimals = intval(substr($amount, $pos + 2, strlen($amount))); // extract the decimals
$amount = number_format($amount, $decimals, '.', ','); // format the number without E-
}
return $amount;
}
Please note the function will always return a string.
Programming languages have different methods for storing numbers in memory. This is determined by the type of number that is being used. In your case, you have a floating point number (a fraction) that is to large to be stored as a fixed point number ( fractions are stored in this manner depending on their size).
This is a very important feature especially when working with very large or very small numbers. For instance, NASA or spaceX uses special storage methods for its calculations to ensure that the rockets the re-enter earths orbit land where they should.
Also, different storage methods take up different amounts of memory. However, the solution provided above should work. Just remember round off errors might occur with very big or small numbers.

Categories