note 102126 deleted from language.types.float by danbrown

From: Date: Sat, 02 Feb 2013 15:11:53 +0000
Subject: note 102126 deleted from language.types.float by danbrown
References: 1  Groups: php.notes 
Request: Send a blank email to php-notes+get-193500@lists.php.net to get a copy of this message
Note Submitter: Nstiac (info at nstiac dot com) ---- There are many scripts/functions to convert a Hex string to a Floating point number, but i could'nt find any usable function to convert a float2hex (float number to hexadecimal) .. so i went on an made one! .. to my surprise.. it didn't matched the other existing functions results exactly due to different methods used on each .. so i went on an created a complementary function to have both results match float2hex32n<->hex2float32n. <?php /** Complementary functions to CONVERT PHP FLOATING POINT NUMBERS or DECIMALS * (IEEE 754 single-precision 32 bit) TO HEXADECIMAL AND BACK. * * @author NSTIAC (Jorge D. Baigorri Salas) http://www.nstiac.com http://www.n2works.com * @created on 28/Jan/2010 / time spent: 2hours approx. * @special thanks to Thomas Finley's article "Floating Point" * http://tfinley.net/notes/cps104/floating.html * * These functions allow to convert any php floating point numbers with the * notation 1.234 (or fixed point numbers) into their corresponding 8 digits * hexadecimal notation. (i.e.- 1557897.40 -> 49BE2C4B <- 1557897.40) by * disregarding their implicit format and treating them at will as either * integer, decimals, binary numbers, hexadecimal values, or plain text. * **/ /** FLOAT2HEX32n * (Convert php float numbers or decimals (single-precision 32bits) to 8 digit Hexadecimal) * Accepts only fixed point notation decimal numbers or fractions on a string (i.e.- "1.23456") * @usage: * float2hex32n("-1557897.13"); returns "c9be2c49" **/ function float2hex32n($number) { //Convert non-decimal to decimal. $number=number_format($number,23,'.',''); //Get the integer portion of $number if ($number>0) { $intnumber=substr($number,0,strpos($number,".")); } else { //Check whether is a negative number to remove - sign. $intnumber=substr($number,1,strpos($number,".")); } //Convert integer to binary $binint=decbin($intnumber); //Get the decimal fraction of the number $pointnumber=substr($number,strpos($number,".")); //Add a 0 to treat as single decimal fraction $pointnumber="0".$pointnumber; //Convert decimal values to base 2 $tmppoint=number_format($pointnumber*2,23,'.',''); for ($i=0; $i<23; $i++) { $binpoint.=substr((string)$tmppoint,0,1); $tmppoint=substr((string)$tmppoint,1); $tmppoint=number_format($tmppoint*2,23,'.',''); } //Gather both values to get base 2 binary fraction $scibin=$binint.".".$binpoint; //Find fraction separator "." position $exp=strpos($scibin,"."); //Transform to scientific notation (1.x^exp) $scibin=substr($binint,0,1).".".substr($binint,1).$binpoint; //Create mantissa if ($scibin>1) { $mantissa=substr($scibin,2); } else { $mantissa=substr($scibin,1); } //Fill mantissa to 23 bit value $fill23=23-strlen($mantissa); for ($i=0; $i<$fill23; $i++) { $mantissa.="0"; } //Convert fraction separator position to exponent value if ($exp>0) { $exp--; } //Adjust to binary notation exponent value $exp+=127; //Convert to 8 bit binary $exp=decbin($exp); //Find 1 bit sign value if ($number>0) { $sign=0; } else { $sign=1; } //Compose final binary value $binfinal=$sign.$exp.$mantissa; //Reorganizae number into 4digit/bits packets and //finally convert to decimal value and to hex. $hexfinal.=dechex(bindec(substr($binfinal,0,4))); $hexfinal.=dechex(bindec(substr($binfinal,4,4))); $hexfinal.=dechex(bindec(substr($binfinal,8,4))); $hexfinal.=dechex(bindec(substr($binfinal,12,4))); $hexfinal.=dechex(bindec(substr($binfinal,16,4))); $hexfinal.=dechex(bindec(substr($binfinal,20,4))); $hexfinal.=dechex(bindec(substr($binfinal,24,4))); $hexfinal.=dechex(bindec(substr($binfinal,28,4))); return $hexfinal; } /** Using either function will return a value which can be used on the other function * to return the original input. (Hope it helps =) **/ ?> Second function (HEX2FLOAT32n) converts Hexadecimal 8 digit strings to fixed decimals float numbers. (complementary to FLOAT2HEX32n above) <?php /** Complementary functions to CONVERT PHP FLOATING POINT NUMBERS or DECIMALS * (IEEE 754 single-precision 32 bit) TO HEXADECIMAL AND BACK. * * @author NSTIAC (Jorge D. Baigorri Salas) http://www.nstiac.com http://www.n2works.com * @created on 28/Jan/2010 / time spent: 2hours approx. * @special thanks to Thomas Finley's article "Floating Point" * http://tfinley.net/notes/cps104/floating.html * * These functions allow to convert any php floating point numbers with the * notation 1.234 (or fixed point numbers) into their corresponding 8 digits * hexadecimal notation. (i.e.- 1557897.40 -> 49BE2C4B <- 1557897.40) by * disregarding their implicit format and treating them at will as either * integer, decimals, binary numbers, hexadecimal values, or plain text. * **/ /** HEX2FLOAT32n * (Convert 8 digit hexadecimal values to fixed decimals float numbers (single-precision 32bits) * Accepts 8 digit hexadecimal values on a string (i.e.- F1A9B02C) and single integer to fix number of decimals * @usage: * hex2float32n("c9be2c49",2); returns -> "-1557897.13" **/ function hex2float32n($number,$nd) { //Separate each hexadecimal digit for ($i=0; $i<strlen($number); $i++) { $hex[]=substr($number,$i,1); } //Convert each hexadecimal digit to integer for ($i=0; $i<count($hex); $i++) { $dec[]=hexdec($hex[$i]); } //Convert each decimal value to 4bit binary and join on a string for ($i=0; $i<count($dec); $i++) { $binfinal.=sprintf("%04d",decbin($dec[$i])); } //Get sign 1bit value $sign=substr($binfinal,0,1); //Get exponent 8bit value $exp=substr($binfinal,1,8); //Get mantissa 23bit value $mantissa=substr($binfinal,9); //Convert & adjunt binary exponent to integer $exp=bindec($exp); $exp-=127; //Assign mantissa to pre-scientific binary notation $scibin=$mantissa; //Split $scibin into integral & fraction parts through exponent $binint=substr($scibin,0,$exp); $binpoint=substr($scibin,$exp); //Convert integral binary part to decimal integer $intnumber=bindec("1".$binint); //Split each binary fractional digit for ($i=0; $i<strlen($binpoint); $i++) { $tmppoint[]=substr($binpoint,$i,1); } //Reverse order to work backwards $tmppoint=array_reverse($tmppoint); //Convert base 2 digits to decimal $tpointnumber=number_format($tmppoint[0]/2,strlen($binpoint),'.',''); for ($i=1; $i<strlen($binpoint); $i++) { $pointnumber=number_format($tpointnumber/2,strlen($binpoint),'.',''); $tpointnumber=$tmppoint[$i+1].substr($pointnumber,1); } //Join both decimal section to get final number $floatfinal=$intnumber+$pointnumber; //Convert to positive or negative based on binary sign bit if ($sign==1) { $floatfinal=-$floatfinal; } //Format float number to fixed decimals required return number_format($floatfinal,$nd,'.',''); } /** Using either function will return a value which can be used on the other function * to return the original input. (Hope it helps =) **/ ?>

« previous php.notes (#193500) next »