bobbfwed Posted September 11, 2008 Share Posted September 11, 2008 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 } ?> Quote Link to comment https://forums.phpfreaks.com/topic/123825-solved-help-with-big-numbers-and/ Share on other sites More sharing options...
Mchl Posted September 11, 2008 Share Posted September 11, 2008 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 Quote Link to comment https://forums.phpfreaks.com/topic/123825-solved-help-with-big-numbers-and/#findComment-639325 Share on other sites More sharing options...
bobbfwed Posted September 11, 2008 Author Share Posted September 11, 2008 ah, I didn't think of 31 bits....stupid signed variables. There's no way to unsign them for this operation is there (I want 32 bits!)? Is there even a way to handle variables in PHP as not signed (no negative value available)? Quote Link to comment https://forums.phpfreaks.com/topic/123825-solved-help-with-big-numbers-and/#findComment-639330 Share on other sites More sharing options...
Mchl Posted September 11, 2008 Share Posted September 11, 2008 Manual says: no Quote Link to comment https://forums.phpfreaks.com/topic/123825-solved-help-with-big-numbers-and/#findComment-639331 Share on other sites More sharing options...
Mchl Posted September 11, 2008 Share Posted September 11, 2008 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 Quote Link to comment https://forums.phpfreaks.com/topic/123825-solved-help-with-big-numbers-and/#findComment-639337 Share on other sites More sharing options...
sasa Posted September 11, 2008 Share Posted September 11, 2008 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); ?> Quote Link to comment https://forums.phpfreaks.com/topic/123825-solved-help-with-big-numbers-and/#findComment-639417 Share on other sites More sharing options...
bobbfwed Posted September 12, 2008 Author Share Posted September 12, 2008 Or, smaller (and probably a good deal faster), but only works up to (around 2^57 -- maybe someone can explain why): function remainder ($value, $div) { $tmp = floor($value / $div); return ($value - ($tmp * $div)); } Quote Link to comment https://forums.phpfreaks.com/topic/123825-solved-help-with-big-numbers-and/#findComment-639838 Share on other sites More sharing options...
Mchl Posted September 12, 2008 Share Posted September 12, 2008 Probably that's where double float precision ends (although I think it should've ended much sooner). Double float has precision of approx 14 significant digits. Quote Link to comment https://forums.phpfreaks.com/topic/123825-solved-help-with-big-numbers-and/#findComment-639861 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.