PHP.mk документација

Броеви со подвижна запирка

Почист и полокален преглед на PHP референцата, со задржана структура од PHP.net и подобра читливост за примери, секции и белешки.

language.types.float.php PHP.net прокси Преводот се освежува
Оригинал на PHP.net
Патека language.types.float.php Локална патека за оваа страница.
Извор php.net/manual/en Оригиналниот HTML се реупотребува и локално се стилизира.
Режим Прокси + превод во позадина Кодовите, табелите и белешките остануваат читливи во истиот тек.
Броеви со подвижна запирка

Референца за `language.types.float.php` со подобрена типографија и навигација.

language.types.float.php

Броеви со подвижна запирка

Броевите со подвижна запирка (познати и како „флоатс“, „даблс“ или „реални броеви“) може да се специфицираат користејќи која било од следниве синтакса:

<?php
$a
= 1.234;
$b = 1.2e3;
$c = 7E-10;
$d = 1_234.567; // as of PHP 7.4.0
?>

Формално од PHP 7.4.0 (претходно, подвлекувањата не биле дозволени):

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

Големината на флоат е зависна од платформата, иако максимум од приближно 1.8e308 со прецизност од околу 14 децимални цифри е честа вредност (64 битен IEEE формат).

Ги ескејпува специјалните знаци во стринг за употреба во SQL изјава

Прецизност на броеви со подвижна запирка

Броевите со подвижна запирка имаат ограничена прецизност. Иако зависи од системот, PHP обично го користи IEEE 754 формат со двојна прецизност, што ќе даде максимална релативна грешка поради заокружување во редот од 1.11e-16. Неелементарните аритметички операции може да дадат поголеми грешки и, се разбира, мора да се земе предвид пропагацијата на грешките кога се комбинираат неколку операции.

Дополнително, рационални броеви кои се точно претставливи како броеви со подвижна запирка во база 10, како 0.1 or 0.7, немаат точна претстава како броеви со подвижна запирка во база 2, која се користи внатрешно, без оглед на големината на мансата. Оттука, тие не можат да се претворат во нивните внатрешни бинарни пандан без мал губиток на прецизност. Ова може да доведе до збунувачки резултати: на пример, floor((0.1+0.7)*10) обично ќе врати 7 наместо очекуваното 8, бидејќи внатрешната претстава ќе биде нешто како 7.9999999999999991118....

Затоа никогаш не верувајте им на резултатите од броевите со подвижна запирка до последната цифра, и не ги споредувајте директно броевите со подвижна запирка за еднаквост. Ако е потребна поголема прецизност, функциите за математика со произволна прецизност and gmp се достапни.

За „едноставно“ објаснување, видете го » водичот за броеви со подвижна запирка кој исто така се нарекува „Зошто моите броеви не се собираат?“

Конвертирање во децимален број

Од низи

Ако низата е numeric , или водечки број, тогаш тој ќе се реши до соодветната вредност на флоат, инаку се претвора во нула (0).

Од други типови

За вредности од други типови, конверзијата се врши со претворање на вредноста во int прво, а потоа во float. Види Конвертирање во цел број Користење на PHP од командната линија

Забелешка:

As certain types have undefined behavior when converting to intКако што одредени типови имаат недефинирано однесување при конверзија во float.

, ова е исто така случај при конверзија во

Споредба на броеви со пловечка запирка

Како што е забележано во предупредувањето погоре, тестирањето на вредности со пловечка запирка за еднаквост е проблематично, поради начинот на кој тие се претставени внатрешно. Сепак, постојат начини за правење споредби на вредности со пловечка запирка што ги заобиколуваат овие ограничувања.

$a and $b За тестирање на вредности со пловечка запирка за еднаквост, се користи горна граница на релативната грешка поради заокружување. Оваа вредност е позната како машинска епсилон, или единица заокружување, и е најмалата прифатлива разлика во пресметките.

се еднакви на 5 цифри на прецизност.

<?php
$a
= 1.23456789;
$b = 1.23456780;
$epsilon = 0.00001;

if (
abs($a - $b) < $epsilon) {
echo
"true";
}
?>

NaN

Некои нумерички операции можат да резултираат со вредност претставена со константата NANПример #1 Споредба на броеви со пловечка запирка true, ќе имаат резултат од false.

Кога корисникот ќе кликне некаде на сликата, придружната форма ќе биде предадена на серверот со две дополнителни променливи: NAN . Овој резултат претставува недефинирана или неможност за претставување вредност во пресметките со пловечка запирка. Секое лабаво или строго споредување на оваа вредност со која било друга вредност, вклучувајќи ја и самата себе, но освен NAN претставува кој било број на различни вредности, is_nan().

Белешки од корисници 10 белешки

не треба да се споредуваат со други вредности, вклучувајќи ја и самата себе, и наместо тоа треба да се проверуваат со помош на
12 години пред
$x = 8 - 6.4;  // which is equal to 1.6
$y = 1.6;
var_dump($x == $y); // is not true

PHP 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 true

This happens probably because $x is not really 1.6, but 1.599999.. and var_dump shows it to you as being 1.6.
catalin dot luntraru at gmail dot com
21 години пред
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.
www.sarioz.com
пред 23 години
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.
feline at NOSPAM dot penguin dot servehttp dot com
пред 9 години
To compare two numbers use:

$epsilon = 1e-6;

if(abs($firstNumber-$secondNumber) < $epsilon){
   // equals
}
lwiwala at gmail dot com
пред 23 години
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?
backov at spotbrokers-nospamplz dot com
пред 15 години
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;
  }
?>
magicaltux at php dot net
20 години пред
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!
Luzian
20 години пред
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) == 1960

Rule of thumb, if it has a decimal point, use the BCMath functions.
rick at ninjafoo dot com
пред 22 години
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.
james dot cridland at virginradio dot co dot uk
пред 14 години
<?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...
На оваа страница

Автоматски outline од активната документација.

Насловите ќе се појават тука по вчитување.

Попрегледно читање

Примерите, changelog табелите и user notes се визуелно издвоени за да не се губат во долгата содржина.

Брз совет Користи го outline-от Скокни директно на главните секции од активната страница.
Извор Оригиналниот линк останува достапен Кога ти треба целосен upstream context, отвори го PHP.net во нов tab.