I am trying to get the sum of 1 + 2 + ... + 1000000000, but I'm getting funny results in PHP and Node.js.
PHP
$sum = 0;
for($i = 0; $i <= 1000000000 ; $i++) {
$sum += $i;
}
printf("%s", number_format($sum, 0, "", "")); // 500000000067108992
Node.js
var sum = 0;
for (i = 0; i <= 1000000000; i++) {
sum += i ;
}
console.log(sum); // 500000000067109000
The correct answer can be calculated using
1 + 2 + ... + n = n(n+1)/2
Correct answer = 500000000500000000, so I decided to try another language.
GO
var sum , i int64
for i = 0 ; i <= 1000000000; i++ {
sum += i
}
fmt.Println(sum) // 500000000500000000
But it works fine! So what is wrong with my PHP and Node.js code?
Perhaps this a problem of interpreted languages, and that's why it works in a compiled language like Go? If so, would other interpreted languages such as Python and Perl have the same problem?
Python works:
>>> sum(x for x in xrange(1000000000 + 1))
500000000500000000
Or:
>>> sum(xrange(1000000000+1))
500000000500000000
Python's int auto promotes to a Python long which supports arbitrary precision. It will produce the correct answer on 32 or 64 bit platforms.
This can be seen by raising 2 to a power far greater than the bit width of the platform:
>>> 2**99
633825300114114700748351602688L
You can demonstrate (with Python) that the erroneous values you are getting in PHP is because PHP is promoting to a float when the values are greater than 2**32-1:
>>> int(sum(float(x) for x in xrange(1000000000+1)))
500000000067108992
Your Go code uses integer arithmetic with enough bits to give an exact answer. Never touched PHP or Node.js, but from the results I suspect the math is done using floating point numbers and should be thus expected not to be exact for numbers of this magnitude.
The reason is that the value of your integer variable sum exceeds the maximum value. And the sum you get is result of float-point arithmetic which involves rounding off. Since other answers did not mention the exact limits, I decided to post it.
The max integer value for PHP for:
32-bit version is 2147483647
64-bit version is 9223372036854775807
So it means either you are using 32 bit CPU or 32 bit OS or 32 bit compiled version of PHP. It can be found using PHP_INT_MAX. The sum would be calculated correctly if you do it on a 64 bit machine.
The max integer value in JavaScript is 9007199254740992. The largest exact integral value you can work with is 253 (taken from this question). The sum exceeds this limit.
If the integer value does not exceed these limits, then you are good. Otherwise you will have to look for arbitrary precision integer libraries.
Here is the answer in C, for completeness:
#include <stdio.h>
int main(void)
{
unsigned long long sum = 0, i;
for (i = 0; i <= 1000000000; i++) //one billion
sum += i;
printf("%llu\n", sum); //500000000500000000
return 0;
}
The key in this case is using C99's long long data type. It provides the biggest primitive storage C can manage and it runs really, really fast. The long long type will also work on most any 32 or 64-bit machine.
There is one caveat: compilers provided by Microsoft explicitly do not support the 14 year-old C99 standard, so getting this to run in Visual Studio is a crapshot.
My guess is that when the sum exceeds the capacity of a native int (231-1 = 2,147,483,647), Node.js and PHP switch to a floating point representation and you start getting round-off errors. A language like Go will probably try to stick with an integer form (e.g., 64-bit integers) as long as possible (if, indeed, it didn't start with that). Since the answer fits in a 64-bit integer, the computation is exact.
Perl script give us the expected result:
use warnings;
use strict;
my $sum = 0;
for(my $i = 0; $i <= 1_000_000_000; $i++) {
$sum += $i;
}
print $sum, "\n"; #<-- prints: 500000000500000000
The Answer to this is "surprisingly" simple:
First - as most of you might know - a 32-bit integer ranges from −2,147,483,648 to 2,147,483,647. So, what happens if PHP gets a result, that is LARGER than this?
Usually, one would expect a immediate "Overflow", causing 2,147,483,647 + 1 to turn into −2,147,483,648. However, that is NOT the case. IF PHP Encounters a larger number, it Returns FLOAT instead of INT.
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.
http://php.net/manual/en/language.types.integer.php
This said, and knowing that PHP FLOAT implementation is following the IEEE 754 double precision Format, means, that PHP is able to deal with numbers upto 52 bit, without loosing precision. (On a 32-bit System)
So, at the Point, where your Sum hits 9,007,199,254,740,992 (which is 2^53) The Float value returned by the PHP Maths will no longer be precise enough.
E:\PHP>php -r "$x=bindec(\"100000000000000000000000000000000000000000000000000000\"); echo number_format($x,0);"
9,007,199,254,740,992
E:\PHP>php -r "$x=bindec(\"100000000000000000000000000000000000000000000000000001\"); echo number_format($x,0);"
9,007,199,254,740,992
E:\PHP>php -r "$x=bindec(\"100000000000000000000000000000000000000000000000000010\"); echo number_format($x,0);"
9,007,199,254,740,994
This example Shows the Point, where PHP is loosing precision. First, the last significatn bit will be dropped, causing the first 2 expressions to result in an equal number - which they aren't.
From NOW ON, the whole math will go wrong, when working with default data-types.
•Is it the same problem for other interpreted language such as Python or Perl?
I don't think so. I think this is a problem of languages that have no type-safety. While a Integer Overflow as mentioned above WILL happen in every language that uses fixed data types, the languages without type-safety might try to catch this with other datatypes. However, once they hit their "natural" (System-given) Border - they might return anything, but the right result.
However, each language may have different threadings for such a Scenario.
The other answers already explained what is happening here (floating point precision as usual).
One solution is to use an integer type big enough, or to hope the language will chose one if needed.
The other solution is to use a summation algorithm that knows about the precision problem and works around it. Below you find the same summation, first with with 64 bit integer, then with 64 bit floating point and then using floating point again, but with the Kahan summation algorithm.
Written in C#, but the same holds for other languages, too.
long sum1 = 0;
for (int i = 0; i <= 1000000000; i++)
{
sum1 += i ;
}
Console.WriteLine(sum1.ToString("N0"));
// 500.000.000.500.000.000
double sum2 = 0;
for (int i = 0; i <= 1000000000; i++)
{
sum2 += i ;
}
Console.WriteLine(sum2.ToString("N0"));
// 500.000.000.067.109.000
double sum3 = 0;
double error = 0;
for (int i = 0; i <= 1000000000; i++)
{
double corrected = i - error;
double temp = sum3 + corrected;
error = (temp - sum3) - corrected;
sum3 = temp;
}
Console.WriteLine(sum3.ToString("N0"));
//500.000.000.500.000.000
The Kahan summation gives a beautiful result. It does of course take a lot longer to compute. Whether you want to use it depends a) on your performance vs. precision needs, and b) how your language handles integer vs. floating point data types.
If you have 32-Bit PHP, you can calculate it with bc:
<?php
$value = 1000000000;
echo bcdiv( bcmul( $value, $value + 1 ), 2 );
//500000000500000000
In Javascript you have to use arbitrary number library, for example BigInteger:
var value = new BigInteger(1000000000);
console.log( value.multiply(value.add(1)).divide(2).toString());
//500000000500000000
Even with languages like Go and Java you will eventually have to use arbitrary number library, your number just happened to be small enough for 64-bit but too high for 32-bit.
In Ruby:
sum = 0
1.upto(1000000000).each{|i|
sum += i
}
puts sum
Prints 500000000500000000, but takes a good 4 minutes on my 2.6 GHz Intel i7.
Magnuss and Jaunty have a much more Ruby solution:
1.upto(1000000000).inject(:+)
To run a benchmark:
$ time ruby -e "puts 1.upto(1000000000).inject(:+)"
ruby -e "1.upto(1000000000).inject(:+)" 128.75s user 0.07s system 99% cpu 2:08.84 total
I use node-bigint for big integer stuff:
https://github.com/substack/node-bigint
var bigint = require('bigint');
var sum = bigint(0);
for(var i = 0; i <= 1000000000; i++) {
sum = sum.add(i);
}
console.log(sum);
It's not as quick as something that can use native 64-bit stuff for this exact test, but if you get into bigger numbers than 64-bit, it uses libgmp under the hood, which is one of the faster arbitrary precision libraries out there.
took ages in ruby, but gives the correct answer:
(1..1000000000).reduce(:+)
=> 500000000500000000
To get the correct result in php I think you'd need to use the BC math operators: http://php.net/manual/en/ref.bc.php
Here is the correct answer in Scala. You have to use Longs otherwise you overflow the number:
println((1L to 1000000000L).reduce(_ + _)) // prints 500000000500000000
There's actually a cool trick to this problem.
Assume it was 1-100 instead.
1 + 2 + 3 + 4 + ... + 50 +
100 + 99 + 98 + 97 + ... + 51
= (101 + 101 + 101 + 101 + ... + 101) = 101*50
Formula:
For N= 100:
Output = N/2*(N+1)
For N = 1e9:
Output = N/2*(N+1)
This is much faster than looping through all of that data. Your processor will thank you for it. And here is an interesting story regarding this very problem:
http://www.jimloy.com/algebra/gauss.htm
This gives the proper result in PHP by forcing the integer cast.
$sum = (int) $sum + $i;
Common Lisp is one of the fastest interpreted* languages and handles arbitrarily large integers correctly by default. This takes about 3 second with SBCL:
* (time (let ((sum 0)) (loop :for x :from 1 :to 1000000000 :do (incf sum x)) sum))
Evaluation took:
3.068 seconds of real time
3.064000 seconds of total run time (3.044000 user, 0.020000 system)
99.87% CPU
8,572,036,182 processor cycles
0 bytes consed
500000000500000000
By interpreted, I mean, I ran this code from the REPL, SBCL may have done some JITing internally to make it run fast, but the dynamic experience of running code immediately is the same.
I don't have enough reputation to comment on #postfuturist's Common Lisp answer, but it can be optimized to complete in ~500ms with SBCL 1.1.8 on my machine:
CL-USER> (compile nil '(lambda ()
(declare (optimize (speed 3) (space 0) (safety 0) (debug 0) (compilation-speed 0)))
(let ((sum 0))
(declare (type fixnum sum))
(loop for i from 1 to 1000000000 do (incf sum i))
sum)))
#<FUNCTION (LAMBDA ()) {1004B93CCB}>
NIL
NIL
CL-USER> (time (funcall *))
Evaluation took:
0.531 seconds of real time
0.531250 seconds of total run time (0.531250 user, 0.000000 system)
100.00% CPU
1,912,655,483 processor cycles
0 bytes consed
500000000500000000
Racket v 5.3.4 (MBP; time in ms):
> (time (for/sum ([x (in-range 1000000001)]) x))
cpu time: 2943 real time: 2954 gc time: 0
500000000500000000
Works fine in Rebol:
>> sum: 0
== 0
>> repeat i 1000000000 [sum: sum + i]
== 500000000500000000
>> type? sum
== integer!
This was using Rebol 3 which despite being 32 bit compiled it uses 64-bit integers (unlike Rebol 2 which used 32 bit integers)
I wanted to see what happened in CF Script
<cfscript>
ttl = 0;
for (i=0;i LTE 1000000000 ;i=i+1) {
ttl += i;
}
writeDump(ttl);
abort;
</cfscript>
I got 5.00000000067E+017
This was a pretty neat experiment. I'm fairly sure I could have coded this a bit better with more effort.
ActivePerl v5.10.1 on 32bit windows, intel core2duo 2.6:
$sum = 0;
for ($i = 0; $i <= 1000000000 ; $i++) {
$sum += $i;
}
print $sum."\n";
result: 5.00000000067109e+017 in 5 minutes.
With "use bigint" script worked for two hours, and would worked more, but I stopped it. Too slow.
For the sake of completeness, in Clojure (beautiful but not very efficient):
(reduce + (take 1000000000 (iterate inc 1))) ; => 500000000500000000
AWK:
BEGIN { s = 0; for (i = 1; i <= 1000000000; i++) s += i; print s }
produces the same wrong result as PHP:
500000000067108992
It seems AWK uses floating point when the numbers are really big, so at least the answer is the right order-of-magnitude.
Test runs:
$ awk 'BEGIN { s = 0; for (i = 1; i <= 100000000; i++) s += i; print s }'
5000000050000000
$ awk 'BEGIN { s = 0; for (i = 1; i <= 1000000000; i++) s += i; print s }'
500000000067108992
Category other interpreted language:
Tcl:
If using Tcl 8.4 or older it depends if it was compiled with 32 or 64 bit. (8.4 is end of life).
If using Tcl 8.5 or newer which has arbitrary big integers, it will display the correct result.
proc test limit {
for {set i 0} {$i < $limit} {incr i} {
incr result $i
}
return $result
}
test 1000000000
I put the test inside a proc to get it byte-compiled.
For the PHP code, the answer is here:
The size of an integer is platform-dependent, although a maximum value of about two billion is the usual value (that's 32 bits signed). 64-bit platforms usually have a maximum value of about 9E18. PHP does not support unsigned integers. Integer size can be determined using the constant PHP_INT_SIZE, and maximum value using the constant PHP_INT_MAX since PHP 4.4.0 and PHP 5.0.5.
Harbour:
proc Main()
local sum := 0, i
for i := 0 to 1000000000
sum += i
next
? sum
return
Results in 500000000500000000.
(on both windows/mingw/x86 and osx/clang/x64)
Erlang works:
from_sum(From,Max) ->
from_sum(From,Max,Max).
from_sum(From,Max,Sum) when From =:= Max ->
Sum;
from_sum(From,Max,Sum) when From =/= Max ->
from_sum(From+1,Max,Sum+From).
Results: 41> useless:from_sum(1,1000000000).
500000000500000000
Funny thing, PHP 5.5.1 gives 499999999500000000 (in ~ 30s), while Dart2Js gives 500000000067109000 (which is to be expected, since it's JS that gets executed). CLI Dart gives the right answer ... instantly.
Erlang gives the expected result too.
sum.erl:
-module(sum).
-export([iter_sum/2]).
iter_sum(Begin, End) -> iter_sum(Begin,End,0).
iter_sum(Current, End, Sum) when Current > End -> Sum;
iter_sum(Current, End, Sum) -> iter_sum(Current+1,End,Sum+Current).
And using it:
1> c(sum).
{ok,sum}
2> sum:iter_sum(1,1000000000).
500000000500000000
Smalltalk:
(1 to: 1000000000) inject: 0 into: [:subTotal :next | subTotal + next ].
"500000000500000000"
Related
I wrote a script to find a factors of 600851475143 that lies between 2 and 100. However I get different values when I ran the script on my local machine and when I ran it on Phpfiddle.org On Phpfiddle I get the correct answer of 71 but on my machine the script simple returns 100 which is wrong. What could be causing this? The code is below
<?php
$n = 600851475143;
for ($i=2; $i < 100; $i++) {
$result = ($n/$i);
if (is_int($result)) {
break;
return $i;
}
}
echo $i;
?>
PHP Manual: Arithmetic Operators:
The division operator ("/") returns a float value unless the two operands are integers (or strings that get converted to integers) and the numbers are evenly divisible, in which case an integer value will be returned.
Your local machine is using 32-bit integers, the largest of which is 2147483647. Either you've got a 32-bit build or you're on Windows using a PHP version prior to 7.
Because 600851475143 is larger than your maximum integer it is converted to a float, and your division will therefore always return a float as well.
If you
var_dump(600851475143/71)
on your local system you'll get
float(8462696833)
while any system using 64-bit integers will give you
int(8462696833)
as 600851475143 and 71 are well within 64-bit bounds.
A method that works across both 32 and 64-bit systems is to check if there is remainder of division using fmod(), e.g.:
$n = 600851475143;
for ($i=2; $i < 100; $i++) {
if (!fmod($n, $i)) {
break;
}
}
echo $i;
Will give you 71 regardless of integer size.
The problem is that the result of your division is always a float so your condition will never match.
A possible solution would be to cast it to a string and check if all characters are digits:
if (ctype_digit((string) $result)) {
That would result in 71, see an example.
I've just come across an interesting question from ComputerGuru on Hacker News and no comment seems to give a convincing answer.
Why does mt_rand(1, PHP_INT_MAX) always return an odd number?
I am not the author of the original question.
http://3v4l.org/dMbat
for ($i=0;$i<10000;$i++)
{
echo mt_rand(1, PHP_INT_MAX)."\n";
}
output:
8571620074060775425
7401021871338029057
4351677773593444353
1801559362708176897
7848614552286527489
...
PHP_INT_MAX here is 263-1 (64-bit signed int max).
However, mt_rand() doesn't handle values this large. The Mersenne twister internally generates 32-bit words, and PHP's mt_getrandmax() is only 231-1 (it throws away the highest bit).
To generate a value in your requested min to max range, mt_rand first gets the 0 to 231-1 random number, then scales it using this formula:
x = ((x / (mt_getrandmax() + 1)) * (max - min + 1)) + min;
(See the source of rand.c and php_rand.h.)
Basically it blindly scales the internally generated number to fit the overlarge range, without even raising a warning. Multiplying to fit the overlarge range generates a lot of zeroes in the low bits, then adding min (which is 1) makes the result odd.
The problem is more dramatic in hexadecimal, where you can see that the low 32 bits of each number are completely non-random:
for ($i = 0; $i < 10000; $i++) {
printf("%016x\n", mt_rand(1, PHP_INT_MAX));
}
Output:
41e0449b00000001
53d33d7c00000001
6ec8855700000001
234140e000000001
13a4581900000001
77547beb00000001
35a0660a00000001
0d0cd44200000001
...
There is a note in the manual that tries to warn about this, although it understates the problem:
The distribution of mt_rand() return values is biased towards even numbers on 64-bit builds of PHP when max is beyond 232. This is because if max is greater than the value returned by mt_getrandmax(), the output of the random number generator must be scaled up.
(It says it's biased towards even numbers, but that's only true when min is even.)
What is the minimum value allowed for mt_rand()? Is it the same value for 32 bit and 64 bit machines? How could I generate a 32 bit integer using mt_rand() (note that it doesn't need to be highly random)?
BACKGROUND WHY I AM ASKING: I have a 64 bit development physical server and a 32 bit production VPS. Just realized the production server was not generating PKs spanning the full range. To figure out what is going on, I ran the following script. The 64 bit machine never (or at least I've never witnessed) matches, but the 32 bit matches about 50% of the time.
<?php
date_default_timezone_set('America/Los_Angeles');
ini_set('display_errors', 1);
error_reporting(E_ALL);
$count=0;
for ($i = 0; $i <= 10000; $i++) {
$rand=2147483648+mt_rand(-2147483647,2147483647); //Spans 1 to 4294967295 where 0 is reserved
if($rand==2147483649){$count++;}
}
echo('mt_getrandmax()='.mt_getrandmax().' count='.$count);
output
mt_getrandmax()=2147483647 count=5034
TL;DR: To get a random integer in the full range of possible integers, use:
function random_integer() {
$min = defined('PHP_INT_MIN') ? PHP_INT_MIN : (-PHP_INT_MAX-1);
return mt_rand($min, -1) + mt_rand(0, PHP_INT_MAX);
}
For PHP 7, you can use random_int().
Under the hood (1, 2), PHP is doing this:
$number = random_number_between_0_and_0x7FFFFFFF_using_Mersenne_Twister;
$number = $min + (($max - $min + 1.0) * ($number / (0x7FFFFFFF + 1.0)));
Notice $max - $min. When max is set to the top end and min is anything negative, an overflow occurs. Therefore, the maximum range is PHP_INT_MAX. If your maximum value is PHP_INT_MAX, then your minimum is necessarily 0.
Now for the back story. PHP implements the 32-bit Mersenne Twister algorithm. This gives us random integers between [0, and 2^31-1). If you ask for any other range, PHP scales that number using a simple binning function. That binning function includes a subtraction that can lead to overflow, and this problem.
Thus if you want to get a range larger than could be represented by an integer in PHP, you have to add intervals together, like so:
mt_rand(PHP_INT_MIN, -1) + mt_rand(0, PHP_INT_MAX);
Note that PHP_INT_MIN is available since PHP 7, so you'll need to calculate a suitable minimum for your environment before then.
As an aside, notice that 2^31-1 is what getrandmax() returns. People mistakenly believe that on a 64-bit machine getrandmax() will return 2^63-1. That's not true. getrandmax() returns the maximum integer the algorithm will return, which is always 2^31-1.
You can generate a 32 bit integer like this:
$rand = unpack("l", openssl_random_pseudo_bytes(4));
This is a problem that is noted in the PHP docs over here
This works fine on 64 bit Linux:
<?php
printf ("%08x\n", mt_rand (0, 0xFFFFFFFF));
?>
but on our 32 bit Linux development server, it's always yielding 00000000.
On that same machine, this:
<?php
printf ("%08x\n", mt_rand (0, 0xFFFFFFF0));
?>
seems to always yield either 00000000 or a number in the range fffffff2 to ffffffff. This:
<?php
printf ("%08x\n", mt_rand (0, 0xFFFFFF00));
?>
gives numbers where the last two digits vary, and so on through at least 0xF0000000.
However, this:
<?php
printf ("%08x\n", mt_rand (0, 0x7FFFFFFF));
?>
works fine
A bug report is added here.
There has been no word whether PHP is fixing this yet.
In the meantime you can use the mt_rand function between the max_rand and you should be fine
Example Usage
$rand=mt_rand(1,2147483647)+mt_rand(0,2147483647);
Derived from this question : (Java) How does java do modulus calculations with negative numbers?
Anywhere to force PHP to return positive 51?
update
Looking for a configuration setting to fix, instead hard-guessing
Or other math function like bcmath?
updated
Not entire convinced by that java answer, as it does not take account of negative modulus
-13+(-64) =?
Anyway, the post you referenced already gave the correct answer:
$r = $x % $n;
if ($r < 0)
{
$r += abs($n);
}
Where $x = -13 and $n = 64.
If GMP is available, you can use gmp_mod
Calculates n modulo d. The result is always non-negative, the sign of d is ignored.
Example:
echo gmp_strval(gmp_mod('-13', '64')); // 51
Note that n and d have to be GMP number resources or numeric strings. Anything else won't work¹
echo gmp_strval(gmp_mod(-13, 64));
echo gmp_mod(-13, 64);
will both return -51 instead (which is a bug).
¹ running the above in this codepad, will produce 51 in all three cases. It won't do that on my development machine.
The modulo operation should find the remainder of division of a number by another. But strictly speaking in most mainstream programming languages the modulo operation malfunctions if dividend or/and divisor are negative. This includes PHP, Perl, Python, Java, C, C++, etc.
Why I say malfunction? Because according to mathematic definition, a remainder must be zero or positive.
The simple solution is to handle the case yourself:
if r < 0 then r = r + |divisor|;
|divisor| is the absolute value of divisor.
Another solution is to use a library (as #Gordon pointed). However I wouldn't use a library to handle a simple case like this.
I hate using if in this case when you can calculate it right away.
$r = ($x % $n + $n) % $n;
when $n is positive.
The PHP manual says that
The result of the modulus operator % has the same sign as the dividend — that is, the result of $a % $b will have the same sign as $a. For example
so this is not configurable. Use the options suggested in the question you linked to
How can I calculate the value of pi in PHP up to X decimal numbers.
4 decimal points
3.141
64 decimal points
3.141592653589793238462643383279502884197169399375105820974944592
Found the source for the broken link #Konamiman posted.
Compared the results to: http://www.angio.net/pi/digits/50.txt and they are the same.
// Source: http://mgccl.com/2007/01/22/php-calculate-pi-revisited
function bcfact($n)
{
return ($n == 0 || $n== 1) ? 1 : bcmul($n,bcfact($n-1));
}
function bcpi($precision)
{
$num = 0;$k = 0;
bcscale($precision+3);
$limit = ($precision+3)/14;
while($k < $limit)
{
$num = bcadd($num, bcdiv(bcmul(bcadd('13591409',bcmul('545140134', $k)),bcmul(bcpow(-1, $k), bcfact(6*$k))),bcmul(bcmul(bcpow('640320',3*$k+1),bcsqrt('640320')), bcmul(bcfact(3*$k), bcpow(bcfact($k),3)))));
++$k;
}
return bcdiv(1,(bcmul(12,($num))),$precision);
}
echo bcpi(1000);
Calculating PI in php?
Why calculate when we already have the M_PI constant?
M_PI contains the value 3.14159265358979323846.
10000 decimal places for PI is quite a number.
See: http://www.php.net/manual/en/math.constants.php
You can calculate Pi by the Chudnosky series. If you have a server with a very high ram you can easily calculate Pi to many decimal places. If you want to get it to some specific decimal place then, increase the efforts to a really large number and use substr to shorten it to your required decimal place. If you think this process is very slow, then you can get pi value by searching it on google.
PHP cannot hold a number that long as far as I know, but 22/7 is an ancient way to calculate PI, though that will not be any better than the PI constant included in PHP. Perhaps you are trying to output a long string of PI as an exercise.