note 79322 deleted from function.base-convert by danbrown
| From: | danbrown@php.net | Date: | Sat, 02 Jul 2011 01:45:06 +0000 |
| Subject: | note 79322 deleted from function.base-convert by danbrown | ||
| References: | 1 | Groups: | php.notes |
| Request: | Send a blank email to php-notes+get-181152@lists.php.net to get a copy of this message | ||
Note Submitter: Todd Stokes @ Georgia Tech
----
I wrote a function to fix the problem stated above about floating point numbers. (this is especially
useful for arithmetic coding, which is what I'm working on) It's not tremendously robust,
but it gets the job done for "simple" float values.
function floatbin($myfloat, $precision=16, $return_int_part=true) {
//echo "complete: $myfloat\n";
$binary_string = "";
if($return_int_part) {
$binary_string = decbin($myfloat);
$binary_string .= ".";
$fractional_part = $myfloat-intval($myfloat);
} else {
$fractional_part = explode(".",$myfloat);
$fractional_part = ".".$fractional_part[1];
}
//echo "fractional: $fractional_part\n";
for ($i=1; $i < $precision+1; $i++) {
$binary_fraction = 1/pow(2,$i);
if($fractional_part >= $binary_fraction) {
$binary_string .= "1";
$fractional_part = $fractional_part - $binary_fraction;
} else {
$binary_string .= "0";
}
if($fractional_part == 0) {
break;
}
//echo "order: $binary_fraction\t\t";
//echo "state: $fractional_part\n";
}
return $binary_string;
}
// no problem
$myfloat = 1.5;
$decfloat = base_convert($myfloat,10,2);
echo "result: $decfloat\n"; // returns 1111 (wrong)
$decfloat = floatbin($myfloat, 32);
echo "result: $decfloat\n"; // returns 1.1 (correct)
$decfloat = floatbin($myfloat,16,false);
echo "result: $decfloat\n"; // returns 1 (correct)
// no problem
$myfloat = 4.125;
$decfloat = base_convert($myfloat,10,2);
echo "result: $decfloat\n"; // returns 1000000011101 (wrong)
$decfloat = floatbin($myfloat, 32);
echo "result: $decfloat\n"; // returns 100.001 (correct)
$decfloat = floatbin($myfloat,16,false);
echo "result: $decfloat\n"; // returns 001 (correct)
// will be truncated, so the inverse will not be ==
$myfloat = 12.3456;
$decfloat = base_convert($myfloat,10,2);
echo "result: $decfloat\n"; // returns 11110001001000000 (wrong)
$decfloat = floatbin($myfloat, 32);
echo "result: $decfloat\n"; // returns 1100.01011000011110010011110111011001 (correct,
truncated)
$decfloat = floatbin($myfloat,16,false);
echo "result: $decfloat\n"; // returns 0101100001111001 (correct, truncated more)
// a case on where passing false is useful, so the inverse will not be ==
$myfloat = 777777777777.777777;
$decfloat = base_convert($myfloat,10,2);
echo "result: $decfloat\n"; // wrong
$decfloat = floatbin($myfloat, 32);
echo "result: $decfloat\n"; // wrong
$decfloat = floatbin($myfloat,16,false);
echo "result: $decfloat\n"; // correct, but truncated