/** * Converts any positive integer between any two bases ranging from `2` to `16` * * @param fNumber|string $number The positive integer to convert * @param integer $from_base The base to convert from - must be between `2` and `16` * @param integer $to_base The base to convert to - must be between `2` and `16` * @return string The number converted to the new base */ public static function baseConvert($number, $from_base, $to_base) { if ($number instanceof fNumber && $from_base != 10) { throw new fProgrammerException('The from base specified, %s, is not valid for an fNumber object', $from_base); } if (strlen($number) && $number[0] == '+') { $number = substr($number, 1); } if (!ctype_xdigit($number)) { throw new fProgrammerException('The number specified, %s, does not appear to be a positive integer. Negative numbers and fractions are not supported due the different encoding schemes that can be used.', $number); } if (!is_numeric($from_base) || $from_base < 2 || $from_base > 16) { throw new fProgrammerException('The from base specified, %1$s, is not valid base between %2$s and %3$s', $from_base, '2', '16'); } if (!is_numeric($to_base) || $to_base < 2 || $to_base > 16) { throw new fProgrammerException('The to base specified, %1$s, is not valid base between %2$s and %3$s', $from_base, '2', '16'); } $base_string = '0123456789ABCDEF'; $base_map = array('A' => 10, 'B' => 11, 'C' => 12, 'D' => 13, 'E' => 14, 'F' => 15); /* Convert input number to base 10 */ if ($from_base != 10) { $length = strlen($number); $decimal = new fNumber('0'); $base_num = new fNumber($from_base); for ($i = 0; $i < $length; $i++) { $char = strtoupper($number[$i]); $value = new fNumber(isset($base_map[$char]) ? $base_map[$char] : $char); $decimal = $decimal->add($value->mul($base_num->pow($length - ($i + 1)))->round(0)); } } elseif (!$number instanceof fNumber) { $decimal = new fNumber($number); } else { $decimal = $number; } $output = ''; if ($to_base != 10) { do { $frac = $decimal->div($to_base, 3)->__toString(); $frac = '0' . substr($frac, strpos($frac, '.')); $x = (int) ($frac * $to_base + 1.5); $output = $base_string[$x - 1] . $output; $decimal = $decimal->div($to_base, 0); } while ($decimal->gt('0.0')); } else { $output = $decimal->__toString(); } return $output; }
/** * @dataProvider powProvider */ public function testPow($input, $power, $output, $scale) { $num = new fNumber($input); $this->assertSame($output, $num->pow($power, $scale)->__toString()); }