Delicious Bookmark this on Delicious Share on Facebook SlashdotSlashdot It! Digg! Digg



PHP : Function Reference : Mathematical Functions : base_convert

base_convert

Convert a number between arbitrary bases (PHP 4, PHP 5)
string base_convert ( string number, int frombase, int tobase )

Example 1138. base_convert() example

<?php
$hexadecimal
= 'A37334';
echo
base_convert($hexadecimal, 16, 2);
?>

The above example will output:

101000110111001100110100

Related Examples ( Source code ) » base_convert


Code Examples / Notes » base_convert

matt aka junkie

You seem to not see the simplicity of using assembly-esque ideals when inverting colors...
<?
// precond: $color is a hex integer
// postcond: returns inversion
function InvertColor($color)
{
 return (int) 0xffffff - $color;
}
?>


scott

This would seem to be limited to 31 bits, ie. the range of values that can be converted is 0 - 2147483647 in decimal.
Also, this will convert negative values to positive values, unlike DecHex() which will return a null string for negative values.
From what I have observed (using PHP 3.0.11) the following statements will set both a and c to a null string and set b to positive 1.
$a = base_convert (2147483648, 10, 16);
$b = base_convert (-1, 10, 16);
$c = dechex (-1);


kx

There's an useful function custombase_convert(), which seems to be very useful, for example, to implement genealogical trees model proposed by Miguel Sofer (http://darwin.zoology.gla.ac.uk/~rpage/ MyToL/www/downloads/trees.pdf). Unfortunately, Fips' code has a bug. To make it work correctly you should replace line
      while ($decVal > 0)
with this:
      while ($decVal > 0 || $pos >=0)


mike

There are a few functions posted here to inverse or invert a hex color code yet none of them have actually worked for me.
This function will take a hex color code string such as '#00FF00' and return the inversed or inverted hex color code string of '#FF00FF'.
<?
function inverseColor($hex) {
if(substr($hex, 0, 1) == '#') $hex = substr($hex, 1);

$r = str_pad(dechex(255 - hexdec(substr($hex, 0, 2)) ),2,'0',STR_PAD_LEFT);
$g = str_pad(dechex(255 - hexdec(substr($hex, 2, 2)) ),2,'0',STR_PAD_LEFT);
$b = str_pad(dechex(255 - hexdec(substr($hex, 4, 2)) ),2,'0',STR_PAD_LEFT);
return strtoupper('#'.$r.$g.$b);
}
?>


kiam

Refering to the function posted by Michael Renner, I would change the line
 $result = $tostring{$divide} . $result;
in
 $result = $chars{$divide} . $result;
as $divide seems garanted to be less than $tobase.
That also eliminates the need of the variable $tostring.
-- Kiam


cj dennis

Really huge numbers might be truncated at both ends.
eg:
<?php
$binary="11010101001111010001110101000100011110010110110".
"001111000010001010001111001100011010110110010010011010".
"001011010000001001011111110001010101101101011010101010".
"000100011101110010110010100111110001010010111010110011".
"001111111100011001011011001110001111110000101011010010";
print(strtoupper(base_convert($binary, 2, 16)));
?>
will output:
9E8EA23CB63C0000000000000000000000000000000000000000000000000000 (64 hex digits)
when the correct result would be:
6A9E8EA23CB63C228F31AD9268B4097F156D6AA11DCB29F14BACCFF196CE3F0AD2 (66 hex digits)
Notice that as well as the result showing '0's after B63C which you would expect it is also missing the first 6A before 9E.


gateschris

if your worried about little/big edian affecting your dec to binary conversions, or just want to convert large numbers then try this bit of code:
<?
// this little bit of code is simply to convert a 64bit number.
function convert_num ($value) {
$value = (string) $value;
while (!preg_match('/^0*$/', $value) && $j < 65) {
 $cumulate = '';
 $rem = '';
 for ($i = 0; $i < strlen($value); $i++) {
  if ($cumulate == '') {
   if (floor(($value[$i] + $rem) / 2)) {
    $cumulate .= floor(($value[$i] + $rem) / 2);
   }
  } else {
   $cumulate .= floor(($value[$i] + $rem) / 2);
  }
  $rem = $value [$i] % 2 * 10;
 }
 $r = floor($rem / 10);
 $re .= $r;
 $value = $cumulate;
 $j++;
}  
return $re;
}
print convert_num (65535);
?>


lindsay

If you need to use base_convert with numbers larger then 32 bit, the following gmp implementation of base_convert should work.
<?php
/*use gmp library to convert base. gmp will convert numbers > 32bit*/
function gmp_convert($num, $base_a, $base_b)
{
       return gmp_strval ( gmp_init($num, $base_a), $base_b );
}
?>


sam_at_compasspointmedia.com

If you haven't already figured it out from the text, the higest base you can encode in is 36 (because z is 35),  try this
<?php
$compactIt = base_convert('999',10,37);  //or anything higher
?>
and you'll get a warning.


fips

I wrote a function for converting numbers not only into 0-9 and a-z:
-----
<?php
function custombase_convert($numstring, $baseFrom = "0123456789", $baseTo = "0123456789")
{
$numstring = (string) $numstring;
$baseFromLen = strlen($baseFrom);
$baseToLen = strlen($baseTo);
if ($baseFrom == "0123456789") // No analyzing needed, because $numstring is already decimal
{
$decVal = (int) $numstring;
} else {
$decVal = 0;
for ($len = (strlen($numstring) - 1); $len >= 0; $len--)
{
$char = substr($numstring, 0, 1);
$pos = strpos($baseFrom, $char);
if ($pos !== FALSE)
{
$decVal += $pos * ($len > 0 ? pow($baseFromLen, $len) : 1);
}
$numstring = substr($numstring, 1);
}
}
if ($baseTo == "0123456789") // No converting needed, because $numstring needs to be converted to decimal
{
$numstring = (string) $decVal;
} else {
$numstring = FALSE;
$nslen = 0;
$pos = 1;
while ($decVal > 0)
{
$valPerChar = pow($baseToLen, $pos);
$curChar = floor($decVal / $valPerChar);
if ($curChar >= $baseToLen)
{
$pos++;
} else {
$decVal -= ($curChar * $valPerChar);
if ($numstring === FALSE)
{
$numstring = str_repeat($baseTo{1}, $pos);
$nslen = $pos;
}
$numstring = substr($numstring, 0, ($nslen - $pos)) . $baseTo{$curChar} . substr($numstring, (($nslen - $pos) + 1));
$pos--;
}
}
if ($numstring === FALSE) $numstring = $baseTo{1};
}
return $numstring;
}
?>
------
The function arguments:
$numstring - String with number to convert. (e.g. "15" or "5F")
$baseFrom - Chars of the base the number is in. (e.g. "0123456789" for decimal or "01" for binary)
$baseTo - Chars of the base to convert the number. (e.g. "0123456789" for decimal or "01" for binary)
I wrote it for writing numbers in files, and so I convert between "0123456789" (decimal) and "\x01\x02\x03...\xFF" - uses very low disc space :-) (You could of course also add the null char (\x00), but >I< need it to seperate the numbers)


david dot leppek

I was working on an application that needed to convert a 16 digit HEX number to BINARY.  base_convert was choking when the binary number exceeded 54 characters.
$hex_value = “B76ADDCE71CCC6BE”;
$Sample = base_convert ($hex_value, 16, 2);
print $Sample;
//printed: 1011011101101010110111011100111001110001110011001100100000000000
Reviewing the examples here, I didn’t find anything that worked for my exact need.  Here is what I came up with:
function big_convert($string_in, $hex, $bin){
$temp=preg_split('//',$string_in,-1,PREG_SPLIT_DELIM_CAPTURE);
for($i=1;$i< strlen($string_in)+1; $i++) {
$results .= str_pad(base_convert($temp[$i], $hex, $bin), 4, '0', STR_PAD_LEFT);
}
return $results;
}
$hex_value = “B76ADDCE71CCC6BE”;
$Sample = big_convert ($hex_value, 16, 2);
print $Sample;
//printed: 1011011101101010110111011100111001110001110011001100011010111110
Hope this helps...  David Leppek


tomhiggy

I was looking for a function to convert the base encoding of a sha1 hash from base 16 to a custom base 32 (using characters [A-Z2-7], as used by several filesharing applications).
The function custombase_convert() posted by Fips isn't able to cope with numbers above a certain value. It returns the first few (around 10) characters correctly but each character after is a 0 value ('A' in this case).
I've solved the problem for now by requesting in groups of 10 base 16 characters and appending the result to the final base 32 value. If anyone has any better solutions, please let me know.


fiftytoo

I needed a function to invert a hex value, which i used for setting font colors when they were on a colored background, that way i will get a contrasting color.
Im sure there are other reasons to use this, you decide!!
<?php
function InvertColor($hex) {
 return sprintf("%06s",base_convert(($hex ^ 0xFFFFFF),10,16));
 };
print '<td bgcolor="BB2222"><font color="'.InvertColor(0xBB2222).'">Blah</font></td>';
// Prints 44dddd as the font color, which is it's opposite on the color wheel
?>


cfk

Here is the function made by David Leppek who works in both way :
<?php
function big_convert ($number,$to_base) {
$result = "";
switch ($to_base) {
case "2":
$temp = preg_split('//', $number, -1, PREG_SPLIT_DELIM_CAPTURE);
$lng = strlen($number);
for ($i = 1;$i <= $lng;$i++) { $result .= str_pad(base_convert($temp[$i], 16, 2), 4, '0', STR_PAD_LEFT); }
return $result;
break;
case "16":
$bin = substr(chunk_split (strrev($number), 4,'-'), 0, -1);
$temp = preg_split('[-]', $bin, -1, PREG_SPLIT_DELIM_CAPTURE);
for ($i = count($temp)-1;$i >= 0;$i--) { $result = $result . base_convert(strrev($temp[$i]), 2, 16); }
return strtoupper($result);
break;
}
}
$bin = "1011010011110010100100101011011101100101001101001111";
echo $hex = big_convert ($bin,16);
echo big_convert ($hex,2);
?>


michael renner

Here is an unfucked version of the arbitrary-large-number base_convert examples below:
I modified it so that it works as drop-in replacement for base_convert. Attention, no sanity checking is done for the input numbers, anything larger than 36 won't work..
function unfucked_base_convert ($numstring, $frombase, $tobase) {
  $chars = "0123456789abcdefghijklmnopqrstuvwxyz";
  $tostring = substr($chars, 0, $tobase);
  $length = strlen($numstring);
  $result = '';
  for ($i = 0; $i < $length; $i++) {
      $number[$i] = strpos($chars, $numstring{$i});
  }
  do {
      $divide = 0;
      $newlen = 0;
      for ($i = 0; $i < $length; $i++) {
          $divide = $divide * $frombase + $number[$i];
          if ($divide >= $tobase) {
              $number[$newlen++] = (int)($divide / $tobase);
              $divide = $divide % $tobase;
          } elseif ($newlen > 0) {
              $number[$newlen++] = 0;
          }
      }
      $length = $newlen;
      $result = $tostring{$divide} . $result;
  }
  while ($newlen != 0);
  return $result;
}


rithiur

Here is a simple function that works like the function provided by Mr. Fips (See below) with the exception that this can convert numbers of any size. However, note that as the division is performed manually to the number, this function is not very efficient and may not be suitable for converting strings with more than a few hundred numbers (depending on the number bases).
<?php
function custombase_convert_big ($numstring, $frombase, $tobase)
{
$from_count = strlen($frombase);
$to_count = strlen($tobase);
$length = strlen($numstring);
$result = '';
for ($i = 0; $i < $length; $i++)
{
$number[$i] = strpos($frombase, $numstring{$i});
}
do // Loop until whole number is converted
{
$divide = 0;
$newlen = 0;
for ($i = 0; $i < $length; $i++) // Perform division manually (which is why this works with big numbers)
{
$divide = $divide * $from_count + $number[$i];
if ($divide >= $to_count)
{
$number[$newlen++] = (int)($divide / $to_count);
$divide = $divide % $to_count;
}
elseif ($newlen > 0)
{
$number[$newlen++] = 0;
}
}
$length = $newlen;
$result = $tobase{$divide} . $result; // Divide is basically $numstring % $to_count (i.e. the new character)
}
while ($newlen != 0);
return $result;
}
$HEX = "0123456789ABCDEF";
$DEC = "0123456789";
print custombase_convert_big ("FFFFFF", $HEX, $DEC); // Prints "16777215"
$BIN = "01";
$ASCII = "";
for ($i = 0; $i < 256; $i++)
{
$ASCII .= chr($i);
}
$msg = "0100100101110100001000000101011101101111011100100110101101110011";
print custombase_convert_big($msg, $BIN, $ASCII); // Prints "It Works"
?>


fragmer

Here is a much simpler and faster version of the "custombase_convert" function proposed by Mr.Fips (see below). My functions convert decimals to and from custom bases:
<?php
// Decimal > Custom
function dec2any( $num, $base=62, $index=false ) {
if (! $base ) {
$base = strlen( $index );
} else if (! $index ) {
$index = substr( "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" ,0 ,$base );
}
$out = "";
for ( $t = floor( log10( $num ) / log10( $base ) ); $t >= 0; $t-- ) {
$a = floor( $num / pow( $base, $t ) );
$out = $out . substr( $index, $a, 1 );
$num = $num - ( $a * pow( $base, $t ) );
}
return $out;
}
?>
Parameters:
$num - your decimal integer
$base - base to which you wish to convert $num (leave it 0 if you are providing $index or omit if you're using default (62))
$index - if you wish to use the default list of digits (0-1a-zA-Z), omit this option, otherwise provide a string (ex.: "zyxwvu")
<?php
// Custom > Decimal
function any2dec( $num, $base=62, $index=false ) {
if (! $base ) {
$base = strlen( $index );
} else if (! $index ) {
$index = substr( "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", 0, $base );
}
$out = 0;
$len = strlen( $num ) - 1;
for ( $t = 0; $t <= $len; $t++ ) {
$out = $out + strpos( $index, substr( $num, $t, 1 ) ) * pow( $base, $len - $t );
}
return $out;
}
?>
Parameters:
$num - your custom-based number (string) (ex.: "11011101")
$base - base with which $num was encoded (leave it 0 if you are providing $index or omit if you're using default (62))
$index - if you wish to use the default list of digits (0-1a-zA-Z), omit this option, otherwise provide a string (ex.: "abcdef")
I have optimized the functions as much as I could, I hope they'll be helpful to someone.


simon

Here are some functions for converting integers to and from base 256. Converting to base 64 is simple given these.
<?php
function to_base256($number, $from_base = 10) {
$binary_number = base_convert($number, $from_base, 2);
$final_string = "";
$new_length = (ceil(strlen($binary_number)/8)*8);
$binary_number = str_pad($binary_number, $new_length, "0", STR_PAD_LEFT);
for($i=($new_length-8); $i>=0; $i-=8) {
$final_string = chr(base_convert(substr($binary_number, $i, 8), 2, 10)).$final_string;
}
return $final_string;
}
function from_base256($string, $to_base = 10) {
$number = "";
for($i=0; $i<strlen($string); $i++) {
$number .= str_pad(base_convert(ord($string{$i}), 10, 2), 8, "0", STR_PAD_LEFT);
}
return base_convert($number, 2, $to_base);
}
?>
Yes, I know that this would be more efficient if it used mod instead of base_convert, but it needs to work with integers > 32 bits.


ray paseur sometimes uses gmail

function roman_numerals($input_arabic_numeral='') {
if ($input_arabic_numeral == '') { $input_arabic_numeral = date("Y"); } // DEFAULT OUTPUT: THIS YEAR
$arabic_numeral = intval($input_arabic_numeral);
$arabic_numeral_text = "$arabic_numeral";
$arabic_numeral_length = strlen($arabic_numeral_text);
if (!ereg('[0-9]', $arabic_numeral_text)) {
return false; }
if ($arabic_numeral > 4999) {
return false; }
if ($arabic_numeral < 1) {
return false; }
if ($arabic_numeral_length > 4) {
return false; }
$roman_numeral_units = $roman_numeral_tens = $roman_numeral_hundreds = $roman_numeral_thousands = array();
$roman_numeral_units[0] = $roman_numeral_tens[0] = $roman_numeral_hundreds[0] = $roman_numeral_thousands[0] = ''; // NO ZEROS IN ROMAN NUMERALS
$roman_numeral_units[1]='I';
$roman_numeral_units[2]='II';
$roman_numeral_units[3]='III';
$roman_numeral_units[4]='IV';
$roman_numeral_units[5]='V';
$roman_numeral_units[6]='VI';
$roman_numeral_units[7]='VII';
$roman_numeral_units[8]='VIII';
$roman_numeral_units[9]='IX';
$roman_numeral_tens[1]='X';
$roman_numeral_tens[2]='XX';
$roman_numeral_tens[3]='XXX';
$roman_numeral_tens[4]='XL';
$roman_numeral_tens[5]='L';
$roman_numeral_tens[6]='LX';
$roman_numeral_tens[7]='LXX';
$roman_numeral_tens[8]='LXXX';
$roman_numeral_tens[9]='XC';
$roman_numeral_hundreds[1]='C';
$roman_numeral_hundreds[2]='CC';
$roman_numeral_hundreds[3]='CCC';
$roman_numeral_hundreds[4]='CD';
$roman_numeral_hundreds[5]='D';
$roman_numeral_hundreds[6]='DC';
$roman_numeral_hundreds[7]='DCC';
$roman_numeral_hundreds[8]='DCCC';
$roman_numeral_hundreds[9]='CM';
$roman_numeral_thousands[1]='M';
$roman_numeral_thousands[2]='MM';
$roman_numeral_thousands[3]='MMM';
$roman_numeral_thousands[4]='MMMM';
if ($arabic_numeral_length == 3) { $arabic_numeral_text = "0" . $arabic_numeral_text; }
if ($arabic_numeral_length == 2) { $arabic_numeral_text = "00" . $arabic_numeral_text; }
if ($arabic_numeral_length == 1) { $arabic_numeral_text = "000" . $arabic_numeral_text; }
$anu = substr($arabic_numeral_text, 3, 1);
$anx = substr($arabic_numeral_text, 2, 1);
$anc = substr($arabic_numeral_text, 1, 1);
$anm = substr($arabic_numeral_text, 0, 1);
$roman_numeral_text = $roman_numeral_thousands[$anm] . $roman_numeral_hundreds[$anc] . $roman_numeral_tens[$anx] . $roman_numeral_units[$anu];
return ($roman_numeral_text);
}


tim_converse

base_convert expects its string arguments to be integral, and gives nonsensical answers when given floating-point strings.  For example, base_convert("1.0", 10, 2) yields "1100100".  It seems that "1.0" is being interpreted as "100".  (PHP4.0b3).

hkh

An optimized version of fiftytoo InvertColor() function.
<?php
function InvertColor($hex)
{
 return sprintf("%06X", $hex ^ 0xFFFFFF);
}
?>


adamjacobmuller

<?php
function binarycodedstring2dec($binary) {
       $len=strlen($binary);
       $rows=($len/4)-1;
       if (($len%4)>0) {
               $pad=$len+(4-($len%4));
               $binary=str_pad($binary,$pad,"0",STR_PAD_LEFT);
               $len=strlen($binary);
               $rows=($len/4)-1;
       }
       $x=0;
       for ($x=0;$x<=$rows;$x++) {
               $s=($x*4);
               $bins=$binary[$s].$binary[$s+1].$binary[$s+2].$binary[$s+3];
               $num=base_convert($bins,2,10);
               if ($num>9) {
                       die("the string is not a proper binary coded decimal\n");
               } else {
                       $res.=$num;
               }
       }
       return $res;
}
?>
a binary coded decimal is converted by taking groups of four from a decimal string,
for example the binary coded decimal string
1000 = 8
10001000 does not = 136 but 88
so
binarycodedstring2dec(1000) = 8
binarycodedstring2dec(11100000111001)=3839
binarycodedstring2dec(100000111001)=839
i truly have no idea if this function will be useful to anyone, i simply failed a physics midterm because i didn't know this so i wrote this function to make sure i would never forget how to convert binary coded decimals


Change Language


Follow Navioo On Twitter
abs
acos
acosh
asin
asinh
atan2
atan
atanh
base_convert
bindec
ceil
cos
cosh
decbin
dechex
decoct
deg2rad
exp
expm1
floor
fmod
getrandmax
hexdec
hypot
is_finite
is_infinite
is_nan
lcg_value
log10
log1p
log
max
min
mt_getrandmax
mt_rand
mt_srand
octdec
pi
pow
rad2deg
rand
round
sin
sinh
sqrt
srand
tan
tanh
eXTReMe Tracker