Jump to content

Recommended Posts

I am creating a decimal to base-36 (and back) system. But I've found that while getting the remainder of certain large numbers, I get negative numbers, what does this mean? Maybe a system-specific problem (I've tried it on two of my computers).

 

Examples: 2655429305 % 36 = -35; 4128789450 % 36 = -10 ... but there is a long list, and it seems random, but as the number gets higher, there are more negative returns. Is there some arbitrary limit that operator? Try the above math on your PHP system. Just in case it may matter, here is my code:

<?PHP
$b10 = 4128789450; // decimal input here
dectobase36($b10);

echo $b10.'<sub>10</sub><br>';
echo '=<br>';
$b36 = dectobase36($b10);
echo $b36.'<sub>36</sub><br>'; // display base-36 output
echo base36todec($b36); // double check the results


function dectobase36($b10) {
  $b36 = NULL;
  $b102 = $b10;
  while ($b10 > 35) {
    if (($b10 % 36) < 0)
      die($b102.' '.$b10.' '.($b10 % 36).' Decimal value too high.'); // die, and show some values
    $b36 .= chr(ret_ord_value($b10 % 36));
    $b10 = floor($b10 / 36);
  }
  $b36 .= chr(ret_ord_value($b10 % 36));
  return strtoupper(strrev($b36));
}

function ret_ord_value ($num) {
  if ($num > 9)
    return $num + 87;
  else
    return $num + 48;
}



function base36todec($b36) {
  $value = 0;
  $b36 = strtolower($b36);

  for ($i = 0; $i < strlen($b36); $i++)
    $value += ret_let_value(substr($b36, -1 - $i, 1)) * pow(36, $i);
  
  return $value;
}

function ret_let_value ($let) {
  if (ord($let) >= 48 && ord($let) <= 57)
    return $let;
  elseif (ord($let) >= 97 && ord($let) <= 122)
    return ord($let) - 87;
  else
    die($let.'...Bad character.'); // if it is fed a invalid character
}
?>

Link to comment
https://forums.phpfreaks.com/topic/123825-solved-help-with-big-numbers-and/
Share on other sites

Manual says: Remainder $a % $b is negative for negative $a.

Which could mean that youre dealing with overflow (integers are signed 32 bit in most cases)

http://www.php.net/manual/en/language.types.integer.php

 

Both you're examples are larger than 2^31, which means they're overflowing

I've come up with this freaky idea, that might help you, at least for modulo 36

 

Divisible by 36 means divisible by 4 and by nine at the same time.

 

So some pseudocode:

 

check 
if a number made of two last digits is divisible by 4
and
if a sum of all digits is divisible by 9
yes:
remainder is 0
no:
remainder++
decrease your number by one, and check again

or

<?php
function my_r($a, $d){
$l = ceil(strlen($a)/3) * 3;
$a= str_pad($a, $l, '0', STR_PAD_LEFT);
for ($i=0; $i<$l; $i+=3) $ar[] = substr($a,$i,3);
$r = 0;
foreach ($ar as $part) $r = ($r *1000 + $part) % $d;
return $r;
}
$test = '2655429305';
echo my_r($test, 36);
?>

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.