Skip to content

Commit 6cbed1e

Browse files
committed
PHP Big Integer Implementation - V1
1 parent c0a647d commit 6cbed1e

File tree

2 files changed

+286
-1
lines changed

2 files changed

+286
-1
lines changed
Lines changed: 285 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,285 @@
1+
<?php
2+
3+
/*
4+
* Author: Mizanur rahman <[email protected]>
5+
*
6+
* Actual algorithm from: Steven Skiena
7+
*/
8+
9+
10+
define("MAXDIGITS", 1000);
11+
define("PLUS", 1);
12+
define("MINUS", -1);
13+
14+
15+
class BigInteger
16+
{
17+
18+
public $digits;
19+
public $lastDigit;
20+
public $signBit;
21+
22+
public function __construct(string $number)
23+
{
24+
if (strlen($number) == 0) throw new Exception("Number must be present");
25+
26+
if (!preg_match("/(-)?(\d)*/", $number)) {
27+
throw new Exception("Only valid digits are allowed");
28+
}
29+
30+
$this->signBit = PLUS;
31+
32+
if ($number[0] == "-")
33+
$this->signBit = MINUS;
34+
35+
for ($i = 0; $i < MAXDIGITS; $i++) $this->digits[$i] = 0;
36+
37+
$this->lastDigit = -1;
38+
39+
for ($t = strlen($number); $t > 0; $t--) {
40+
$this->lastDigit++;
41+
$this->digits[$this->lastDigit] = $number[$t - 1];
42+
}
43+
44+
if ($number == "0") $this->lastDigit = 0;
45+
}
46+
}
47+
48+
function printBigInteger(BigInteger &$n)
49+
{
50+
if ($n->signBit == MINUS) echo "- ";
51+
for ($i = $n->lastDigit; $i >= 0; $i--)
52+
echo $n->digits[$i];
53+
echo "\n";
54+
}
55+
56+
function intToBigInteger(string $s, BigInteger &$n)
57+
{
58+
if ($s >= 0)
59+
$n->signBit = PLUS;
60+
else
61+
$n->signBit = MINUS;
62+
63+
for ($i = 0; $i < MAXDIGITS; $i++) $n->digits[$i] = 0;
64+
65+
$n->lastDigit = -1;
66+
67+
$t = abs($s);
68+
69+
while ($t > 0) {
70+
$n->lastDigit++;
71+
$n->digits[$n->lastDigit] = ($t % 10);
72+
$t /= 10;
73+
}
74+
75+
if ($s == 0) $n->lastDigit = 0;
76+
}
77+
78+
function initBigInteger(BigInteger &$n)
79+
{
80+
intToBigInteger(0, $n);
81+
}
82+
83+
function zeroJustify(BigInteger &$n)
84+
{
85+
while (($n->lastDigit > 0) && ($n->digits[$n->lastDigit] == 0))
86+
$n->lastDigit--;
87+
88+
if (($n->lastDigit == 0) && ($n->digits[0] == 0))
89+
$n->signBit = PLUS; /* hack to avoid -0 */
90+
}
91+
92+
93+
function digitShift(BigInteger $n, int $d) /* multiply n by 10^d */
94+
{
95+
if (($n->lastDigit == 0) && ($n->digits[0] == 0)) return;
96+
97+
for ($i = $n->lastDigit; $i >= 0; $i--)
98+
$n->digits[$i + $d] = $n->digits[$i];
99+
100+
for ($i = 0; $i < $d; $i++) $n->digits[$i] = 0;
101+
102+
$n->lastDigit = $n->lastDigit + $d;
103+
}
104+
105+
function compareBigInteger(BigInteger &$a, BigInteger &$b)
106+
{
107+
108+
if (($a->signBit == MINUS) && ($b->signBit == PLUS)) return (PLUS);
109+
if (($a->signBit == PLUS) && ($b->signBit == MINUS)) return (MINUS);
110+
111+
if ($b->lastDigit > $a->lastDigit) return (PLUS * $a->signBit);
112+
if ($a->lastDigit > $b->lastDigit) return (MINUS * $a->signBit);
113+
114+
for ($i = $a->lastDigit; $i >= 0; $i--) {
115+
if ($a->digits[$i] > $b->digits[$i]) return (MINUS * $a->signBit);
116+
if ($b->digits[$i] > $a->digits[$i]) return (PLUS * $a->signBit);
117+
}
118+
119+
return 0;
120+
}
121+
122+
function addBigInteger(BigInteger &$a, BigInteger &$b, BigInteger &$c)
123+
{
124+
initBigInteger($c);
125+
126+
if ($a->signBit == $b->signBit)
127+
$c->signBit = $a->signBit;
128+
else {
129+
if ($a->signBit == MINUS) {
130+
$a->signBit = PLUS;
131+
subtractBigInteger($b, $a, $c);
132+
$a->signBit = MINUS;
133+
} else {
134+
$b->signBit = PLUS;
135+
subtractBigInteger($a, $b, $c);
136+
$b->signBit = MINUS;
137+
}
138+
return;
139+
}
140+
141+
$c->lastDigit = max($a->lastDigit, $b->lastDigit) + 1;
142+
$carry = 0;
143+
144+
145+
for ($i = 0; $i <= $c->lastDigit; $i++) {
146+
$c->digits[$i] = ($carry + $a->digits[$i] + $b->digits[$i]) % 10;
147+
$carry = intval(($carry + $a->digits[$i] + $b->digits[$i]) / 10);
148+
}
149+
150+
zeroJustify($c);
151+
}
152+
153+
function subtractBigInteger(BigInteger &$a, BigInteger &$b, BigInteger &$c)
154+
{
155+
initBigInteger($c);
156+
157+
if (($a->signBit == MINUS) || ($b->signBit == MINUS)) {
158+
$b->signBit = -1 * $b->signBit;
159+
addBigInteger($a, $b, $c);
160+
$b->signBit = -1 * $b->signBit;
161+
return;
162+
}
163+
164+
if (compareBigInteger($a, $b) == PLUS) {
165+
subtractBigInteger($b, $a, $c);
166+
$c->signBit = MINUS;
167+
return;
168+
}
169+
170+
$c->lastDigit = max($a->lastDigit, $b->lastDigit);
171+
$borrow = 0;
172+
173+
for ($i = 0; $i <= ($c->lastDigit); $i++) {
174+
$v = ($a->digits[$i] - $borrow - $b->digits[$i]);
175+
if ($a->digits[$i] > 0)
176+
$borrow = 0;
177+
if ($v < 0) {
178+
$v = $v + 10;
179+
$borrow = 1;
180+
}
181+
182+
$c->digits[$i] = $v % 10;
183+
}
184+
185+
zeroJustify($c);
186+
}
187+
188+
189+
function multiplyBigInteger(BigInteger &$a, BigInteger &$b, BigInteger &$c)
190+
{
191+
$numbers = [];
192+
for ($i = 0; $i <= $b->lastDigit; $i++) {
193+
$carry = 0;
194+
$tmp = clone $c;
195+
$tmp->lastDigit = 0;
196+
for ($j = 0; $j <= $a->lastDigit; $j++) {
197+
$tmp->digits[$tmp->lastDigit++] = ($carry + $a->digits[$j] * $b->digits[$i]) % 10;
198+
$carry = intval(($carry + $a->digits[$j] * $b->digits[$i]) / 10);
199+
200+
}
201+
if ($carry > 0) {
202+
$tmp->digits[$tmp->lastDigit] = $carry;
203+
}
204+
205+
digitShift($tmp, $i);
206+
zeroJustify($tmp);
207+
$numbers[] = $tmp;
208+
}
209+
210+
foreach ($numbers as $number) {
211+
$tmp = clone $c;
212+
addBigInteger($number, $tmp, $c);
213+
}
214+
215+
$c->signBit = $a->signBit * $b->signBit;
216+
217+
zeroJustify($c);
218+
}
219+
220+
221+
function divideBigInteger(BigInteger &$a, BigInteger &$b, BigInteger &$c)
222+
{
223+
224+
$row = clone $c;
225+
$tmp = clone $c;
226+
227+
$c->signBit = $a->signBit * $b->signBit;
228+
229+
$asign = $a->signBit;
230+
$bsign = $b->signBit;
231+
232+
$a->signBit = PLUS;
233+
$b->signBit = PLUS;
234+
235+
$c->lastDigit = $a->lastDigit;
236+
237+
for ($i = $a->lastDigit; $i >= 0; $i--) {
238+
digitShift($row, 1);
239+
$row->digits[0] = $a->digits[$i];
240+
$c->digits[$i] = 0;
241+
while (compareBigInteger($row, $b) != PLUS) {
242+
$c->digits[$i]++;
243+
subtractBigInteger($row, $b, $tmp);
244+
$row = clone $tmp;
245+
}
246+
}
247+
248+
zeroJustify($c);
249+
250+
$a->signBit = $asign;
251+
$b->signBit = $bsign;
252+
}
253+
254+
function factorial (int $n, BigInteger &$c) {
255+
256+
intToBigInteger("1", $c);
257+
258+
if($n > 0) {
259+
for($i = 1;$i<=$n;$i++) {
260+
$tmp = clone $c;
261+
$number = new BigInteger($i);
262+
$result = new BigInteger("0");
263+
multiplyBigInteger($number, $tmp, $result);
264+
$c = $result;
265+
}
266+
}
267+
zeroJustify($c);
268+
}
269+
270+
271+
$first = new BigInteger("12345678");
272+
$second = new BigInteger("2222");
273+
$result = new BigInteger("0");
274+
275+
printBigInteger($first);
276+
printBigInteger($second);
277+
278+
//divideBigInteger($first, $second, $result);
279+
$start = microtime(false);
280+
factorial(100, $result);
281+
$end = microtime(false);
282+
printBigInteger($result);
283+
284+
285+

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# PHP-Data-Structure-and-Algorithms
1+
# PHP Data Structures and Algorithms
22

33
Data structure and Algorithm is always important for any programming language. PHP, being one of the most popular language for web development, also requires the pure data structure and algorithm implementations.
44

0 commit comments

Comments
 (0)