3 * PHP Number Base Conversion Functions
\r
4 * Version 1.0 - February 2004
\r
5 * Version 2.0 - January 2005 - converted to using bcmath
\r
6 * Version 2.1 - September 2005 - added decimal point conversion ability
\r
7 * (c) 2004,2005 Paul Gregg <pgregg@pgregg.com>
\r
8 * http://www.pgregg.com
\r
10 * Function: Arbitrary Number Base conversion from base 2 - 62
\r
11 * This file should be included by other php scripts
\r
12 * For normal base 2 - 36 conversion use the built in base_convert function
\r
14 * Open Source Code: If you use this code on your site for public
\r
15 * access (i.e. on the Internet) then you must attribute the author and
\r
16 * source web site: http://www.pgregg.com/projects/
\r
17 * You must also make this original source code available for download
\r
18 * unmodified or provide a link to the source. Additionally you must provide
\r
19 * the source to any modified or translated versions or derivatives.
\r
23 /* Ozh' note: this script:
\r
24 * - allows handling large integers on 32bits machines, which base_convert() does not
\r
25 * - allows encoding upt to base 64 (base_convert() is limited to 36)
\r
26 * - needs PHP extension BCCOMP (http://www.php.net/bccomp)
\r
29 function yourls_dec2base($iNum, $iBase, $iScale=0) { // cope with base 2..62
\r
31 $sChars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
\r
32 $sResult = ''; // Store the result
\r
34 // special case for Base64 encoding
\r
36 $sChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';
\r
38 $sNum = is_integer($iNum) ? "$iNum" : (string)$iNum;
\r
39 $iBase = yourls_intval($iBase); // incase it is a string or some weird decimal
\r
41 // Check to see if we are an integer or real number
\r
42 if (strpos($sNum, '.') !== FALSE) {
\r
43 list ($sNum, $sReal) = explode('.', $sNum, 2);
\r
44 $sReal = '0.' . $sReal;
\r
48 while (bccomp($sNum, 0, $iScale) != 0) { // still data to process
\r
49 $sRem = bcmod($sNum, $iBase); // calc the remainder
\r
50 $sNum = bcdiv( bcsub($sNum, $sRem, $iScale), $iBase, $iScale );
\r
51 $sResult = $sChars[$sRem] . $sResult;
\r
53 if ($sReal != '0') {
\r
55 $fraciScale = $iScale;
\r
56 while($fraciScale-- && bccomp($sReal, 0, $iScale) != 0) { // still data to process
\r
57 if ($LDEBUG) print "<br> -> $sReal * $iBase = ";
\r
58 $sReal = bcmul($sReal, $iBase, $iScale); // multiple the float part with the base
\r
59 if ($LDEBUG) print "$sReal => ";
\r
61 if (bccomp($sReal ,1, $iScale) > -1)
\r
62 list($sFrac, $dummy) = explode('.', $sReal, 2); // get the yourls_intval
\r
63 if ($LDEBUG) print "$sFrac\n";
\r
64 $sResult .= $sChars[$sFrac];
\r
65 $sReal = bcsub($sReal, $sFrac, $iScale);
\r
73 function yourls_base2dec($sNum, $iBase=0, $iScale=0) {
\r
74 $sChars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
\r
77 $iBase = yourls_intval($iBase); // incase it is a string or some weird decimal
\r
79 // special case for Base64 encoding
\r
81 $sChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';
\r
83 // clean up the input string if it uses particular input formats
\r
85 case 16: // remove 0x from start of string
\r
86 if (strtolower(substr($sNum, 0, 2)) == '0x') $sNum = substr($sNum, 2);
\r
88 case 8: // remove the 0 from the start if it exists - not really required
\r
89 if (strpos($sNum, '0')===0) $sNum = substr($sNum, 1);
\r
91 case 2: // remove an 0b from the start if it exists
\r
92 if (strtolower(substr($sNum, 0, 2)) == '0b') $sNum = substr($sNum, 2);
\r
94 case 64: // remove padding chars: =
\r
95 $sNum = str_replace('=', '', $sNum);
\r
97 default: // Look for numbers in the format base#number,
\r
98 // if so split it up and use the base from it
\r
99 if (strpos($sNum, '#') !== false) {
\r
100 list ($sBase, $sNum) = explode('#', $sNum, 2);
\r
101 $iBase = yourls_intval($sBase); // take the new base
\r
104 print("yourls_base2dec called without a base value and not in base#number format");
\r
110 // Convert string to upper case since base36 or less is case insensitive
\r
111 if ($iBase < 37) $sNum = strtoupper($sNum);
\r
113 // Check to see if we are an integer or real number
\r
114 if (strpos($sNum, '.') !== FALSE) {
\r
115 list ($sNum, $sReal) = explode('.', $sNum, 2);
\r
116 $sReal = '0.' . $sReal;
\r
121 // By now we know we have a correct base and number
\r
122 $iLen = strlen($sNum);
\r
124 // Now loop through each digit in the number
\r
125 for ($i=$iLen-1; $i>=0; $i--) {
\r
126 $sChar = $sNum[$i]; // extract the last char from the number
\r
127 $iValue = strpos($sChars, $sChar); // get the decimal value
\r
128 if ($iValue > $iBase) {
\r
129 print("yourls_base2dec: $sNum is not a valid base $iBase number");
\r
132 // Now convert the value+position to decimal
\r
133 $sResult = bcadd($sResult, bcmul( $iValue, bcpow($iBase, ($iLen-$i-1))) );
\r
136 // Now append the real part
\r
137 if (strcmp($sReal, '0') != 0) {
\r
138 $sReal = substr($sReal, 2); // Chop off the '0.' characters
\r
139 $iLen = strlen($sReal);
\r
140 for ($i=0; $i<$iLen; $i++) {
\r
141 $sChar = $sReal[$i]; // extract the first, second, third, etc char
\r
142 $iValue = strpos($sChars, $sChar); // get the decimal value
\r
143 if ($iValue > $iBase) {
\r
144 print("yourls_base2dec: $sNum is not a valid base $iBase number");
\r
147 $sResult = bcadd($sResult, bcdiv($iValue, bcpow($iBase, ($i+1)), $iScale), $iScale);
\r
154 function yourls_base2base($iNum, $iBase, $oBase, $iScale=0) {
\r
155 if (!function_exists('bccomp'))
\r
156 return base_convert($iNum, $iBase, $oBase);
\r
158 if ($iBase != 10) $oNum = yourls_base2dec($iNum, $iBase, $iScale);
\r
159 else $oNum = $iNum;
\r
160 $oNum = yourls_dec2base($oNum, $oBase, $iScale);
\r