## Nombres à virgules flottantes

Les nombres à virgule flottante (aussi connus comme `"floats"`, `"doubles"`, ou `"nombres réels"`) peuvent être spécifiés en utilisant les syntaxes suivantes :

``` <?php\$a = 1.234;\$b = 1.2e3;\$c = 7E-10;\$d = 1_234.567; // à partir de PHP 7.4.0?> ```

Formellement à partir de PHP 7.4.0 (auparavant, les underscores n'étaient pas autorisé) :

```LNUM          [0-9]+(_[0-9]+)*
DNUM          ([0-9]*(_[0-9]+)*[\.]{LNUM}) | ({LNUM}[\.][0-9]*(_[0-9]+)*)
EXPONENT_DNUM (({LNUM} | {DNUM}) [eE][+-]? {LNUM})
```

La taille d'un nombre décimal est dépendante de la plate-forme, cependant, un nombre maximal d'environ 1.8e308 avec une précision sur 14 chiffres est une valeur commune (format 64 bits IEEE).

Avertissement

# Précision des nombres flottants

Les nombres flottants ont une précision limitée. Même s'ils dépendent du système, PHP utilise le format de précision des décimaux IEEE 754, qui donnera une erreur maximale relative de l'ordre de 1.11e-16 (dûe aux arrondis). Les opérations arithmétiques non-élémentaires peuvent donner des erreurs plus importantes et bien sûr les erreurs doivent être prises en compte lorsque plusieurs opérations sont liées.

Aussi, les nombres rationnels exactement représentables sous forme de nombre à virgule flottante en base 10, comme `0.1` ou `0.7`, n'ont pas de représentation exacte comme nombres à virgule flottante en base 2, utilisée en interne, et ce quelle que soit la taille de la mantisse. De ce fait, ils ne peuvent être convertis sans une petite perte de précision. Ceci peut mener à des résultats confus: par exemple, `floor((0.1+0.7)*10)` retournera normalement `7` au lieu de `8` attendu, car la représentation interne sera quelque chose comme `7.9999999999999991118...`.

Ainsi, ne faites jamais confiance aux derniers chiffres d'un nombre flottant, mais aussi, ne comparez pas l'égalité de 2 nombres flottant directement. Si une plus grande précision est nécessaire, les fonctions mathématiques de précision arbitraire et les fonctions gmp sont disponibles.

Pour une explication "simple", voir le » guide relatif aux nombres à virgule flottante.

### Convertir en un nombre flottant

#### Depuis des chaînes de caractères

Si une chaîne est numérique ou numérique de tête alors elle sera transformée en sa valeur flottante correspondante, sinon elle sera convertie à zéro(`0`).

#### Depuis d'autres types

Pour les valeurs d'autres types, la conversion est effectuée en convertissant la valeur d'abord en int puis en float. Voir conversion en entier pour plus d'informations.

Note:

Comme certains types ont un comportement indéfinie lors de la conversion en int, ceci est aussi le cas lors de la conversion en float.

### Comparaison de nombres flottants

Comme dit dans la note ci-dessus, le test d'égalité des valeurs de nombres flottants est problématique, en raison de la façon dont ils sont représentés en interne. Cependant, il existe des façons de réaliser cette comparaison.

Pour tester l'égalité de valeurs de nombres flottants, une borne supérieure de l'erreur relative à l'arrondi est utilisée. Cette valeur est connue comme étant l'epsilon de la machine, ou le `unit roundoff`, et est la différence la plus petite acceptable dans les calculs.

\$a et \$b sont égaux sur 5 nombres après la virgule.

``` <?php\$a = 1.23456789;\$b = 1.23456780;\$epsilon = 0.00001;if(abs(\$a-\$b) < \$epsilon) { echo "true";}?> ```

### NaN

Quelques opérations numériques peuvent donner comme résultat une valeur représentée par la constante `NAN`. Ce résultat représente une valeur indéfinie ou non représentable lors de calculs avec des nombres à virgule flottante. Toute comparaison, même stricte de cette valeur avec une autre valeur, y compris cette constante elle-même, sauf si elle est égale à `true`, donnera une valeur de `false`.

En raison du fait que `NAN` représente tout nombre de valeur différente, `NAN` ne doit pas être comparé à d'autres valeurs, y compris cette constante elle-même, et à la place, elle doit être vérifiée en utilisant la fonction is_nan().

### User Contributed Notes 37 notes

239
catalin dot luntraru at gmail dot com
9 years ago
``` \$x = 8 - 6.4;  // which is equal to 1.6\$y = 1.6;var_dump(\$x == \$y); // is not truePHP thinks that 1.6 (coming from a difference) is not equal to 1.6. To make it work, use round()var_dump(round(\$x, 2) == round(\$y, 2)); // this is trueThis happens probably because \$x is not really 1.6, but 1.599999.. and var_dump shows it to you as being 1.6. ```
103
feline at NOSPAM dot penguin dot servehttp dot com
18 years ago
``` General computing hint: If you're keeping track of money, do yourself and your users the favor of handling everything internally in cents and do as much math as you can in integers. Store values in cents if at all possible. Add and subtract in cents. At every operation that wii involve floats, ask yourself "what will happen in the real world if I get a fraction of a cent here" and if the answer is that this operation will generate a transaction in integer cents, do not try to carry fictional fractional accuracy that will only screw things up later. ```
55
www.sarioz.com
20 years ago
``` just a comment on something the "Floating point precision" inset, which goes: "This is related to .... 0.3333333."While the author probably knows what they are talking about, this loss of precision has nothing to do with decimal notation, it has to do with representation as a floating-point binary in a finite register, such as while 0.8 terminates in decimal, it is the repeating 0.110011001100... in binary, which is truncated.  0.1 and 0.7 are also non-terminating in binary, so they are also truncated, and the sum of these truncated numbers does not add up to the truncated binary representation of 0.8 (which is why (floor)(0.8*10) yields a different, more intuitive, result).  However, since 2 is a factor of 10, any number that terminates in binary also terminates in decimal. ```
17
backov at spotbrokers-nospamplz dot com
20 years ago
``` I'd like to point out a "feature" of PHP's floating point support that isn't made clear anywhere here, and was driving me insane. This test (where var_dump says that \$a=0.1 and \$b=0.1) if (\$a>=\$b) echo "blah!"; Will fail in some cases due to hidden precision (standard C problem, that PHP docs make no mention of, so I assumed they had gotten rid of it). I should point out that I originally thought this was an issue with the floats being stored as strings, so I forced them to be floats and they still didn't get evaluated properly (probably 2 different problems there). To fix, I had to do this horrible kludge (the equivelant of anyway): if (round(\$a,3)>=round(\$b,3)) echo "blah!"; THIS works. Obviously even though var_dump says the variables are identical, and they SHOULD BE identical (started at 0.01 and added 0.001 repeatedly), they're not. There's some hidden precision there that was making me tear my hair out. Perhaps this should be added to the documentation? ```
james dot cridland at virginradio dot co dot uk
20 years ago
``` The 'floating point precision' box in practice means:<? echo (69.1-floor(69.1)); ?>Think this'll return 0.1?It doesn't - it returns 0.099999999999994<? echo round((69.1-floor(69.1))); ?>This returns 0.1 and is the workaround we use.Note that<? echo (4.1-floor(4.1)); ?>*does* return 0.1 - so if you, like us, test this with low numbers, you won't, like us, understand why all of a sudden your script stops working, until you spend a lot of time, like us, debugging it.So, that's all lovely then. ```
Luzian
17 years ago
``` Be careful when using float values in strings that are used as code later, for example when generating JavaScript code or SQL statements. The float is actually formatted according to the browser's locale setting, which means that "0.23" will result in "0,23". Imagine something like this:\$x = 0.23;\$js = "var foo = doBar(\$x);";print \$js;This would result in a different result for users with some locales. On most systems, this would print:var foo = doBar(0.23);but when for example a user from Germany arrives, it would be different:var foo = doBar(0,23);which is obviously a different call to the function. JavaScript won't state an error, additional arguments are discarded without notice, but the function doBar(a) would get 0 as parameter. Similar problems could arise anywhere else (SQL, any string used as code somewhere else). The problem persists, if you use the "." operator instead of evaluating the variable in the string.So if you REALLY need to be sure to have the string correctly formatted, use number_format() to do it! ```
lwiwala at gmail dot com
6 years ago
``` To compare two numbers use:\$epsilon = 1e-6;if(abs(\$firstNumber-\$secondNumber) < \$epsilon){   // equals} ```
zelko at mojeime dot com
12 years ago
``` <?php   \$binarydata32 = pack('H*','00000000');   \$float32 = unpack("f", \$binarydata32); // 0.0   \$binarydata64 = pack('H*','0000000000000000');   \$float64 = unpack("d", \$binarydata64); // 0.0?>I get 0 both for 32-bit and 64-bit numbers.But, please don't use your own "functions" to "convert" from float to binary and vice versa. Looping performance in PHP is horrible. Using pack/unpack you use processor's encoding, which is always correct. In C++ you can access the same 32/64 data as either float/double or 32/64 bit integer. No "conversions".To get binary encoding:<?php   \$float32 = pack("f", 5300231);   \$binarydata32 =unpack('H*',\$float32); //"0EC0A14A"   \$float64 = pack("d", 5300231);   \$binarydata64 =unpack('H*',\$float64); //"000000C001385441"?>And my example from half a year ago:<?php    \$binarydata32 = pack('H*','0EC0A14A');    \$float32 = unpack("f", \$binarydata32); // 5300231       \$binarydata64 = pack('H*','000000C001385441');    \$float64 = unpack("d", \$binarydata64); // 5300231?>And please mind the Big and Little endian boys... ```
magicaltux at php dot net
13 years ago
``` In some cases you may want to get the maximum value for a float without getting "INF".var_dump(1.8e308); will usually show: float(INF)I wrote a tiny function that will iterate in order to find the biggest non-infinite float value. It comes with a configurable multiplicator and affine values so you can share more CPU to get a more accurate estimate.I haven't seen better values with more affine, but well, the possibility is here so if you really thing it's worth the cpu time, just try to affine more.Best results seems to be with mul=2/affine=1. You can play with the values and see what you get. The good thing is this method will work on any system.<?php  function float_max(\$mul = 2, \$affine = 1) {    \$max = 1; \$omax = 0;    while((string)\$max != 'INF') { \$omax = \$max; \$max *= \$mul; }    for(\$i = 0; \$i < \$affine; \$i++) {      \$pmax = 1; \$max = \$omax;      while((string)\$max != 'INF') {        \$omax = \$max;        \$max += \$pmax;        \$pmax *= \$mul;      }    }    return \$omax;  }?> ```
sam at rmcreative dot ru
5 months ago
``` Instead of 0.00001 you should use PHP_FLOAT_EPSILON constant if you're not at PHP <= 7.2 ```
rick at ninjafoo dot com
17 years ago
``` Concider the following:(19.6*100) != 1960  echo gettype(19.6*100) returns 'double', However even ..... (19.6*100) !== (double)1960 19.6*100 cannot be compaired to anything without manually casting it as something else first. (string)(19.6*100) == 1960Rule of thumb, if it has a decimal point, use the BCMath functions. ```
-1
pcunha at gmail dot com
10 years ago
``` To simply convert 32 bits float from hex to float: <?php function hexfloat (\$hex){     return (unpack("f", pack('H*',\$hex))); } ?> This may be useful for arduino interface with php. ```
-1
8 years ago
``` I've just come across this issue with floats when writing a function for pricing. When converting from string to a float, with 2 digits of precision, the issue with comparing floats can pop up and give inconsistent results due to the conversion process.An easier way rather than relying on the mentioned epsilon method is to use number_format (at least for me as I'll remember it!).Example function that can return an unexpected result:if((float)\$a == (float)\$b) {echo true;} else {echo false;}echo's false in this example.Using number format here to trim down the precision (2 point precision being mostly used for currencies etc, although higher precisions should be correctly catered for by number_format), will return an expected result:if(number_format((float)\$a, 2) == number_format((float)\$b, 2)) {echo true;} else {echo false;}Correctly echo's true. ```
-1
yobberowich at gmail dot com
6 years ago
``` @catalynYou write about 8-6.4 being not equal to 1.6. The true reason is that absolute epsilon value depends on the exponent and that conversion to float rounds down to next possible value. 6.4 has a bigger rounding error than 1.6 and the resulting error from computing 8-6.4 is bigger than rounding error of 1.6 itself. (float)1.6 is the number closest to being 1.6 while (float)(8-6.4) is bigger than 1.6 - conversion to float rounds down. So, 1.6 will be like 1.599999 and 8-6.4 will be somewhat like 1.600001The solution would be to use decimal math for constant expressions. ```
-1
Anonymous
13 years ago
``` Calculations involving float types become inaccurate when it deals with numbers with more than approximately 8 digits long where ever the decimal point is.  This is because of how 32bit floats are commonly stored in memory.  This means if you rely on float types while working with tiny fractions or large numbers, your calculations can end up between tiny fractions to several trillion off.This usually won't matter when converting to binary memory storage form and editing many applications' float memory addresses directly, or dealing with smaller length numbers.  But if you're working with larger scale numbers and decimals, it's best to switch to working with other types: http://www.php.net/manual/en/refs.math.php ```
-1
inforsci at gmail dot com
13 years ago
``` convert 32bit HEX values into IEEE 754 floating point <?php \$strHex = "C45F82ED"; \$bin = str_pad(base_convert(\$strHex, 16, 2), 32, "0", STR_PAD_LEFT); \$sign = \$bin; \$exp = bindec(substr(\$bin, 1, 8)) - 127; \$man = (2 << 22) + bindec(substr(\$bin, 9, 23)); \$dec = \$man * pow(2, \$exp - 23) * (\$sign ? -1 : 1); echo "Answer = " . \$dec . "<BR>\n"; ?> ```
-3
jack at surfacefinishtech dot com
10 years ago
``` <?php/** hex2float * (Convert 8 digit hexadecimal value to float (single-precision 32bits) * Accepts 8 digit hexadecimal values in a string * @usage: * hex2float32n("429241f0"); returns -> "73.128784179688" * */function hex2float(\$number) {    \$binfinal = sprintf("%032b",hexdec(\$number));    \$sign = substr(\$binfinal, 0, 1);    \$exp = substr(\$binfinal, 1, 8);    \$mantissa = "1".substr(\$binfinal, 9);    \$mantissa = str_split(\$mantissa);    \$exp = bindec(\$exp)-127;    \$significand=0;    for (\$i = 0; \$i < 24; \$i++) {        \$significand += (1 / pow(2,\$i))*\$mantissa[\$i];    }    return \$significand * pow(2,\$exp) * (\$sign*-2+1);}?> ```
-3
Julian L
12 years ago
``` Convert a hex string into a 32-bit IEEE 754 float number.  This function is 2 times faster then the below hex to 32bit function.  This function only changes datatypes (string to int) once. Also, this function is a port from the hex to 64bit function from below.<?phpfunction hexTo32Float(\$strHex) {    \$v = hexdec(\$strHex);    \$x = (\$v & ((1 << 23) - 1)) + (1 << 23) * (\$v >> 31 | 1);    \$exp = (\$v >> 23 & 0xFF) - 127;    return \$x * pow(2, \$exp - 23);}?><?php//exampleecho hexTo32Float("C4028000"); // outputs: -522echo hexTo32Float("457F9000"); // outputs: 4089echo hexTo32Float("2D7F5");    // outputs: 6.00804264307E-39echo hexTo32Float("0002D7F5"); // outputs: 6.00804264307E-39echo hexTo32Float("47D9F95E"); // outputs: 111602.734375?> ```
-2
kjohnson at zootweb dot com
15 years ago
``` PHP switches from the standard decimal notation to exponential notation for certain "special" floats. You can see a partial list of such "special" values with this:<?phpfor( \$tmp = 0, \$i = 0; \$i < 100; \$i++ ) {    \$tmp += 100000;    echo round(\$tmp),"\n";}?>So, if you add two floats, end up with a "special" value, e.g. 1.2E+6, then put that value unmodified into an update query to store the value in a decimal column, say, you will likely get a failed transaction, since the database will see "1.2E+6" as varchar data, not decimal. Likewise, you will likely get an XSD validation error if you put the value into xml.I have to be honest: this is one of the strangest things I have seen in any language in over 20 years of coding, and it is a colossal pain to work around. ```
-3
davidszilardd at gmail dot com
11 years ago
``` The function returns 5 for 5,000 because if there is no decimal point, then the first strpos will be FALSE, and FALSE < 1 is TRUE so the condition will be still true.It should be checked whether strpos returns a valid position:<?phpfunction str2num(\$str){       if (strpos(\$str, '.') !== FALSE && strpos(\$str,    ',') !== FALSE && strpos(\$str, '.') < strpos(\$str,','))          {             \$str = str_replace('.','',\$str);             \$str = strtr(\$str,',','.');                    }         else        {             \$str = str_replace(',','',\$str);                    }                 return (float)\$str; }?> ```
-3
m dot lebkowski+php at gmail dot com
15 years ago
``` Just another note about the locales. Consider the following code:<?php     // in polish locale decimal separator is ","    setlocale(LC_ALL, "pl_PL");    \$a = 5/2;    echo (float)(string)\$a;    /// prints "2", so the decimal part is dropped?>This causes very serious problems in my opinion. In some locale combination the typecasting can be destructive.Maybe when locale decimal separator is ",", then (float)"2,5" should be recognized as "two and a half"? Anyway - bare that in mind and be very careful when casting floats to strings and back. ```
-2
dev at maintainfit dot com
20 years ago
``` I was programming an accounting application in MySql that required me to sum a collection of floats and ensure that they equal zero before commiting a transaction, but as seen above a sum of floats cannot always be trusted (as was my case).  I kept getting a very small remainder (like 1.4512431231e-14).  Since I had used number_format(num,2) to set the precision of the numbers in the database to only two (2) decimal places, when the time comes to calculate the sum I simply multiply every number by ten (10), therby eliminating and decimal places and leaving me with integers to preform my sum.  This worked great. ```
-2
jrf_php dot net at NO_SPAM dot adviesenzo dot nl
5 years ago
``` Just on the off-chance that someone is ever looking for it - here a regular expression which will work in PHP to recognize both floats and integers:<?php\$array = array('1263576', '1.234', '1.2e3', '7E-10', 'not a number', 'a 1234 as part of a string', 'here\'s a float: 35E1');\$regex = '`(?:    # Exponential floats    [+-]?(?:(?:(?P<LNUM>[0-9]+)|(?P<DNUM>([0-9]*\.(?P>LNUM)|(?P>LNUM)\.[0-9]*)))[eE][+-]?(?P>LNUM))    # Or ordinary floats    |(?P>DNUM)    # Or integers    |(?P>LNUM))`x';foreach ( \$array as \$string) {    if (preg_match(\$regex, \$string, \$matches) === 1) {        var_dump(\$matches);    }}?>Will output:string(7) "1263576"string(5) "1.234"string(5) "1.2e3"string(5) "7E-10"string(4) "1234"string(4) "35E1" ```
-3
Bob
14 years ago
``` In MySQL, many floating point number types can have a range specified using 2 values, the "precision" and the "scale" E.g. 'float(precision,scale)' for the datatype. This syntax means a number may be <precision> bits long, but may only have <scale> bits after the decimal point. E.g. a 'float(5,2)' field may have the values -999.99 to 999.99.Here is a function to validate a PHP float using this syntax:<?phpfunction validate_float(\$float, \$precision, \$scale){    \$max = (float)str_pad("", \$precision-\$scale, '9').'.'.str_pad("", \$scale, '9');    \$min = (float)"-\$max";    if((\$float < \$min) || (\$float > \$max)) return false;    else return true;}?> ```
-3
nathanb at php dot net
8 years ago
``` An extremely small and simple example of this is:<?php  echo intval(19.31 * 100);?> ```
-4
francois dot barbier at gmail dot com
13 years ago
``` As "m dot lebkowski+php at gmail dot com" (http://www.php.net/language.types.float#81416) noted 9 comments below :When PHP converts a float to a string, the decimal separator used depends on the current locale conventions.However, to declare a floating point number, one must always use a full stop otherwhise the code would be locale dependent (imagine the nightmare):<?php\$float = 1.5;           // float(1.5)\$float = 1,5;           // Parse error: syntax error, unexpected ','\$float = (float) '1.5'; // float(1.5)\$float = (float) '1,5'; // float(1)?>Now, if you have a string containing a localized number, you can convert it back to a floating point number using the following function:<?php/** * Convert a localized number string into a floating point number * * @param      string \$sNumber The localized number string to convert. * @return     float The converted number. */function str2num(\$sNumber){    \$aConventions = localeConv();    \$sNumber = trim((string) \$sNumber);    \$bIsNegative = (0 === \$aConventions['n_sign_posn'] && '(' === \$sNumber{0} && ')' === \$sNumber{strlen(\$sNumber) - 1});    \$sCharacters = \$aConventions['decimal_point'].                   \$aConventions['mon_decimal_point'].                   \$aConventions['negative_sign'];    \$sNumber = preg_replace('/[^'.preg_quote(\$sCharacters).'\d]+/', '', trim((string) \$sNumber));    \$iLength = strlen(\$sNumber);    if (strlen(\$aConventions['decimal_point']))    {        \$sNumber = str_replace(\$aConventions['decimal_point'], '.', \$sNumber);    }    if (strlen(\$aConventions['mon_decimal_point']))    {        \$sNumber = str_replace(\$aConventions['mon_decimal_point'], '.', \$sNumber);    }    \$sNegativeSign = \$aConventions['negative_sign'];    if (strlen(\$sNegativeSign) && 0 !== \$aConventions['n_sign_posn'])    {        \$bIsNegative = (\$sNegativeSign === \$sNumber{0} || \$sNegativeSign === \$sNumber{\$iLength - 1});        if (\$bIsNegative)        {            \$sNumber = str_replace(\$aConventions['negative_sign'], '', \$sNumber);        }    }    \$fNumber = (float) \$sNumber;    if (\$bIsNegative)    {        \$fNumber = -\$fNumber;    }    return \$fNumber;}?>Example:<?phpsetLocale(LC_ALL, 'fr_BE.UTF-8'); // decimal separator is now a comma\$float = -123456.789;\$string = (string) \$float;var_dump(\$float);           // float(-123456,789)var_dump(\$string);          // string(11) "-123456,789"var_dump((float) \$string);  // float(-123456)var_dump(str2num(\$string)); // float(-123456,789)?>It also works with strings returned by the number_format() function:<?phpsetLocale(LC_ALL, 'fr_BE.UTF-8'); // decimal separator is now a comma\$conv = localeconv();\$float = -123456.789;\$string = \$conv['int_curr_symbol'].number_format(\$float, \$conv['frac_digits'], \$conv['decimal_point'], \$conv['thousands_sep']);var_dump(\$float);           // float(-123456,789)var_dump(\$string);          // string(15) "EUR -123.456,79"var_dump((float) \$string);  // float(0)var_dump(str2num(\$string)); // float(-123456,79)?> ```
-3
luizvid at gmail dot com
8 years ago
``` An effective way to compare two real numbers (including floating point numbers) with high accuracy and still be able to set precision is using the BC Math function bccomp();For instance:<?php    \$a = 1.23456789;    \$b = 1.23456780;    \$precision = 5;    if(bccomp(\$a, \$b, \$precision)  === 0 ) {        echo "true";    } // true?><?php    \$a = sprintf('%.17f', 0.1+0.2);    \$b = 0.3;    if(bccomp(\$a, \$b, 17)  !== 0 ) {        echo "FALSE";    } // FALSE?> ```
-4
manasseh at smartcomputerinc.com
12 years ago
``` I found that 00000000 hex was converting to 1.0 decimal. From the Wikipedia article on IEEE-754 floating point:The true significand includes 23 fraction bits to the right of the binary point and an implicit leading bit (to the left of the binary point) with value 1 unless the exponent is stored with all zeros.In hex2float32n, replace:      \$intnumber=bindec("1".\$binint);with   if (\$exp <> -127)      { \$intnumber=bindec("1".\$binint); };and then 00000000 works correctly without affecting "normal" numbers. ```
-3
alterg79 at gmail dot com
6 years ago
``` For php7.1.2, NAN is interpreted like TRUE when is not a strict compare, so "Any loose or strict comparisons of this value against any other value, including itself, but except TRUE, will have a result of FALSE." it is partially true:Code:    var_dump(NAN || FALSE);    var_dump(NAN && TRUE);    var_dump(NAN === FALSE);    var_dump(NAN === TRUE);    var_dump(NAN === "FDS");    var_dump(NAN === NAN);    var_dump(NAN == NAN);    var_dump(NAN == FALSE);    var_dump(NAN == TRUE);result:bool(true)bool(true)bool(false)bool(false)bool(false)bool(false)bool(false)bool(false)bool(true) ```
-5
zelko at mojeime dot com
12 years ago
``` The was talk about "converting" 32 and 64 bit IEEE754 binary numbers to PHP float. The issue isn't as much converting, since they are already in binary form, as it is casting. PHP doesn't allow direct accessing of memory, but you can still get around a bit.The right was to read floats (32 and 64 bit) is this:<?php    \$binarydata32 = pack('H*','0EC0A14A');    \$float32 = unpack("f", \$binarydata32);        \$binarydata64 = pack('H*','000000C001385441');    \$float64 = unpack("d", \$binarydata64);        var_dump(\$float32,\$float64,\$float32==\$float64);   ?>The result of dump():<?php array(1) {  =>  float(5300231)}array(1) {  =>  float(5300231)}bool(true)?>Note: mind the Big and Little endian boys ```
-3
Eduard
6 years ago
``` In the gettype() manual, it says "(for historical reasons "double" is returned in case of a float, and not simply "float") ".However, I think that internally PHP sometimes uses the C double definition (i.e. a double is twice the size of a float/real). See the example below:<?//Function required to reverse a string on blocks of twofunction strrev_x(\$s, \$x = 2) {    if (\$x <= 1) {        return strrev(\$s);     } else {        return (implode(array_reverse(array_map('implode', array_chunk(str_split(\$s), \$x)))));    }}echo 'double pack'. PHP_EOL;\$tst = pack('d', '1.6');var_dump(strrev_x(bin2hex(\$tst)));\$tst = pack('d', 8-6.4);var_dump(strrev_x(bin2hex(\$tst)));echo 'float pack'. PHP_EOL;\$tst = pack('f', '1.6');var_dump(strrev_x(bin2hex(\$tst)));\$tst = pack('f', 8-6.4);var_dump(strrev_x(bin2hex(\$tst)));?>(The strrev_x-bin2hex combination is just to give printable characters.)Given that PHP treats doubles and floats identically, I'd expected the same string as output, however, the output is:double packstring(16) "3ff999999999999a" //Here you see that there is a minute difference...string(16) "3ff9999999999998"float packstring(8) "3fcccccd" //... which doesn't exist herestring(8) "3fcccccd"So, as an alternative to using  \$float1 === \$float2one could use  pack('f', \$float1) === pack ('f', \$float2)with a big footnote that one should really remember that one is *reducing* your accuracy of the comparison. AFAIK is this the only way (apart from epsilon methods) to securely compare two floats. ```
-5
info at forrest79 dot net
14 years ago
``` My BIN to FLOAT (IEEE754), the first one doesn't work for me: <?php         function binToFloat(\$bin) {             if(strlen(\$bin) > 32) {                 return false;             } else if(strlen(\$bin) < 32) {                 \$bin = str_repeat('0', (32 - strlen(\$bin))) . \$bin;             }             \$sign = 1;             if(intval(\$bin) == 1) {                 \$sign = -1;             }             \$binExponent = substr(\$bin, 1, 8);             \$exponent = -127;             for(\$i = 0; \$i < 8; \$i++) {                 \$exponent += (intval(\$binExponent[7 - \$i]) * pow(2, \$i));             }             \$binBase = substr(\$bin, 9);                        \$base = 1.0;             for(\$x = 0; \$x < 23; \$x++) {                 \$base += (intval(\$binBase[\$x]) * pow(0.5, (\$x + 1)));             }             \$float = (float) \$sign * pow(2, \$exponent) * \$base;             return \$float;         } ?> ```
-4
munteanutraian at gmail dot com
5 years ago
``` Comment on "\$x = 8 - 6.4;  // which is equal to 1.6\$y = 1.6;var_dump(\$x == \$y); // is not true"You can get a string representation with var_export(\$var)var_export(\$x);echo PHP_EOL;var_export(\$y);echo PHP_EOL;will output:1.59999999999999961.6000000000000001Hence, \$x not equals \$y ```
-13
Bob
14 years ago
``` Here is a function to convert an exponential-format float to a decimal-format float; e.g. 1.6e+12 to 1600000000000.It will help addressing the problem specified by kjohnson above.I have tested it, but not in any real world situation so any feedback/improvements/bug-reports would be appreciated.<?phpfunction exp_to_dec(\$float_str)// formats a floating point number string in decimal notation, supports signed floats, also supports non-standard formatting e.g. 0.2e+2 for 20// e.g. '1.6E+6' to '1600000', '-4.566e-12' to '-0.000000000004566', '+34e+10' to '340000000000'// Author: Bob{    // make sure its a standard php float string (i.e. change 0.2e+2 to 20)    // php will automatically format floats decimally if they are within a certain range    \$float_str = (string)((float)(\$float_str));    // if there is an E in the float string    if((\$pos = strpos(strtolower(\$float_str), 'e')) !== false)    {        // get either side of the E, e.g. 1.6E+6 => exp E+6, num 1.6        \$exp = substr(\$float_str, \$pos+1);        \$num = substr(\$float_str, 0, \$pos);                // strip off num sign, if there is one, and leave it off if its + (not required)        if(((\$num_sign = \$num) === '+') || (\$num_sign === '-')) \$num = substr(\$num, 1);        else \$num_sign = '';        if(\$num_sign === '+') \$num_sign = '';                // strip off exponential sign ('+' or '-' as in 'E+6') if there is one, otherwise throw error, e.g. E+6 => '+'        if(((\$exp_sign = \$exp) === '+') || (\$exp_sign === '-')) \$exp = substr(\$exp, 1);        else trigger_error("Could not convert exponential notation to decimal notation: invalid float string '\$float_str'", E_USER_ERROR);                // get the number of decimal places to the right of the decimal point (or 0 if there is no dec point), e.g., 1.6 => 1        \$right_dec_places = ((\$dec_pos = strpos(\$num, '.')) === false) ? 0 : strlen(substr(\$num, \$dec_pos+1));        // get the number of decimal places to the left of the decimal point (or the length of the entire num if there is no dec point), e.g. 1.6 => 1        \$left_dec_places = (\$dec_pos === false) ? strlen(\$num) : strlen(substr(\$num, 0, \$dec_pos));                // work out number of zeros from exp, exp sign and dec places, e.g. exp 6, exp sign +, dec places 1 => num zeros 5        if(\$exp_sign === '+') \$num_zeros = \$exp - \$right_dec_places;        else \$num_zeros = \$exp - \$left_dec_places;                // build a string with \$num_zeros zeros, e.g. '0' 5 times => '00000'        \$zeros = str_pad('', \$num_zeros, '0');                // strip decimal from num, e.g. 1.6 => 16        if(\$dec_pos !== false) \$num = str_replace('.', '', \$num);                // if positive exponent, return like 1600000        if(\$exp_sign === '+') return \$num_sign.\$num.\$zeros;        // if negative exponent, return like 0.0000016        else return \$num_sign.'0.'.\$zeros.\$num;    }    // otherwise, assume already in decimal notation and return    else return \$float_str;}?> ```
-11
helly at php dot net
15 years ago
``` Floating point values have a limited precision. Hence a value might not have the same string representation after any processing. That also includes writing a floating point value in your script and directly printing it without any mathematical operations.If you would like to know more about "floats" and what IEEE 754 is read this: http://docs.sun.com/source/806-3568/ncg_goldberg.html ```
-16
reinaldorock at yahoo dot com dot br
11 years ago
``` Convert locale string into float number <?php function str2num(\$str){   if(strpos(\$str, '.') < strpos(\$str,',')){             \$str = str_replace('.','',\$str);             \$str = strtr(\$str,',','.');                    }         else{             \$str = str_replace(',','',\$str);                    }         return (float)\$str; } str2num('25,01'); //25.01 str2num('2.5,01'); //25.01 str2num('25.01'); //25.01 str2num('2,5.01'); //25.01 ?> ```
-4
Robson Cozendey
1 year ago
``` Beware of NaN and strings in PHP. In other languages (and specifically in Javascript) math operations with non-numerical strings will result in NaN, while in PHP the string is silently converted to 0.So any test like:is_nan('hello, string'); // falsegives the impression that the string is a valid number. ``` 