note 109660 modified in function.base-convert by danbrown
| From: | danbrown@php.net | Date: | Fri, 10 Aug 2012 16:12:43 +0000 |
| Subject: | note 109660 modified in function.base-convert by danbrown | ||
| References: | 1 | Groups: | php.notes |
| Request: | Send a blank email to php-notes+get-190002@lists.php.net to get a copy of this message | ||
If you use base_convert to convert a large (eg. 80-bit) hexadecimal to base-36, you might
observe: ABCDEF00001234567890 (hexadecimal) =>
3O47RE02JZSW0KS8 (base-36) => ABCDEF00001240000000
(hexadecimal) This is normal and is due to the loss of precision
on large numbers. I have written a string-based function using
the built-in BC Math Extension which will overcome this and similar
problems. <?php function
str_baseconvert($str, $frombase=10, $tobase=36) { $str =
trim($str); if (intval($frombase) != 10) { $len =
strlen($str); $q = 0; for ($i=0; $i<$len;
$i++) { $r = base_convert($str[$i], $frombase, 10);
$q = bcadd(bcmul($q, $frombase), $r); }
} else $q = $str; if (intval($tobase)
!= 10) { $s = ''; while
(bccomp($q, '0', 0) > 0) { $r =
intval(bcmod($q, $tobase)); $s = base_convert($r, 10, $tobase) .
$s; $q = bcdiv($q, $tobase, 0);
} } else $s = $q;
return
$s; } ?> Typical
use-cases: 1. Convert a large arbitrary precision number to
base-36. 2. Convert a 32-char hexadecimal UUID (128-bit) to a 25-char base-36
unique key, and vice
versa. Examples: <?php $b16
= 'ABCDEF00001234567890'; $b36 = str_baseconvert($b16, 16,
36); echo ("$b16 (hexadecimal) = $b36 (base-36)
\\n"); $uuid =
'ABCDEF01234567890123456789ABCDEF'; $ukey = str_baseconvert($uuid,
16, 36); echo ("$uuid (hexadecimal) = $ukey (base-36)
\\n"); ?> ABCDEF00001234567890
(hexadecimal) = 3o47re02jzqisvio (base-36) ABCDEF01234567890123456789ABCDEF
(hexadecimal) = a65xa07491kf5zyfpvbo76g33 (base-36)
--was--
If you use base_convert to convert a large (eg. 80-bit) hexadecimal to base-36, you might observe:
ABCDEF00001234567890 (hexadecimal) => 3O47RE02JZSW0KS8 (base-36) => ABCDEF00001240000000
(hexadecimal)
This is normal and is due to the loss of precision on large numbers.
I have written a string-based function using the built-in BC Math Extension which will overcome this
and similar problems.
<?
function str_baseconvert($str, $frombase=10, $tobase=36) {
$str = trim($str);
if (intval($frombase) != 10) {
$len = strlen($str);
$q = 0;
for ($i=0; $i<$len; $i++) {
$r = base_convert($str[$i], $frombase, 10);
$q = bcadd(bcmul($q, $frombase), $r);
}
}
else $q = $str;
if (intval($tobase) != 10) {
$s = '';
while (bccomp($q, '0', 0) > 0) {
$r = intval(bcmod($q, $tobase));
$s = base_convert($r, 10, $tobase) . $s;
$q = bcdiv($q, $tobase, 0);
}
}
else $s = $q;
return $s;
}
?>
Typical use-cases:
1. Convert a large arbitrary precision number to base-36.
2. Convert a 32-char hexadecimal UUID (128-bit) to a 25-char base-36 unique key, and vice versa.
Examples:
<?
$b16 = 'ABCDEF00001234567890';
$b36 = str_baseconvert($b16, 16, 36);
echo ("$b16 (hexadecimal) = $b36 (base-36) \n");
$uuid = 'ABCDEF01234567890123456789ABCDEF';
$ukey = str_baseconvert($uuid, 16, 36);
echo ("$uuid (hexadecimal) = $ukey (base-36) \n");
?>
ABCDEF00001234567890 (hexadecimal) = 3o47re02jzqisvio (base-36)
ABCDEF01234567890123456789ABCDEF (hexadecimal) = a65xa07491kf5zyfpvbo76g33 (base-36)
http://php.net/manual/en/function.base-convert.php