2013-06-20 19 views
14

Witam Próbuję podzielić dwie liczby całkowite np: 12/13, ale zawsze otrzymuję całą liczbę całkowitą 1, a nie liczbę dziesiętną.Jak uzyskać wartość zmiennoprzecinkową podczas dzielenia dwóch liczb całkowitych? (PHP)

Próbowałem typu rzucanie wartości, aby unosić się przed ręką bez powodzenia.

zasadzie wszystko czego chcę to wynik dziesiętny jak: 0,923 ...

$x = 12; 
$y = 13; 
echo $value = $x/$y; //Would like to see 0.923 not 1 
+2

Otrzymuję '0.92307692307692' po uruchomieniu tego –

+5

sprawdź swój php.ini pod kątem wymuszonej liczby dziesiętnej ułamka lub dokładność coś takiego nie może zapamiętać, co jest nazywane. – Dave

+1

Jaką wersję PHP używasz? 'php -v' lub' phpinfo(); ' –

Odpowiedz

8

W normalnych okolicznościach kod powinien zwrócić wartość pływający 0.923076 ...

Powodem masz zaokrąglony całkowita może być dlatego, że masz swój zestaw ini setting dla "precision" do 0, aby to naprawić albo edytować swoje php.ini lub użyj kodu ini_set("precision", 3); w kodzie przed obliczeniami.

Innym sposobem obejścia tego problemu jest użycie BCmath:

echo $value=bcdiv($a, $b, 3); 

a jeszcze inny sposób, bez użycia jakiegokolwiek rozszerzenia jest użyć trochę matematyczne sztuczki, mnożąc wartość, którą chcesz podzielić przez 1000 do uzyskać 3 decimals.
W ten sposób podzielisz 12000 przez 13, a cała część będzie 923, a następnie pomnożona przez 1e3 wstaw przecinek/kropkę przed ostatnimi 3 najbardziej znaczącymi miejscami.

function divideFloat($a, $b, $precision=3) { 
    $a*=pow(10, $precision); 
    $result=(int)($a/$b); 
    if (strlen($result)==$precision) return '0.' . $result; 
    else return preg_replace('/(\d{' . $precision . '})$/', '.\1', $result); 
} 

echo divideFloat($a, $b); // 0.923

+1

Nie. Z precyzją 0 mamy '0.9'.http: //www.php.net/manual/en/ini.core.php#ini.precision nie jest wystarczająco jasne; dłuższe wyjaśnienie: PHP używa własnej implementacji ((v) s) parsowania napisów printf. Tryb '% H' jest używany w łańcuchu formatów: wywołuje on z parametrem' tryb' ustawiony na '2' funkcję' zend_dtoa', w której wskazana jest dokumentacja: '[tryb] 2 ==> maks. (1, ndigity) znaczące cyfry. Daje to wartość zwracaną podobną do wartości ecvt, z wyjątkiem tego, że końcowe zera są pomijane. (Patrz: http://lxr.php.net/xref/PHP_TRUNK/Zend/zend_strtod.c#1457)). Dlatego 'precision = 1' == 'dokładność = 0'. – bwoebi

-1

Wystarczy użyć $ value = (float) ($ x/$ y); // Wynik będzie się unosić.

Pozdrawiam!

+5

- PO wspomniał o próbowaniu typowania. –

9
echo $value = $x/(float) $y; 

jeśli rzucić zmiennej $y jak unosić interpreter użyć zmiennoprzecinkowych podział zamiast podziału całkowitej.

ponieważ jest to domyślny asumpt do używania podziału liczby całkowitej na dwie zmienne całkowite.

Inaczej było w przypadku korzystania $y = 13.0 (zmienna typu float w mianowniku): wyników jest zawsze liczbą pływak

+1

Proszę wyjaśnić, w jaki sposób twoja odpowiedź rozwiązuje problem, aby przyszli użytkownicy mogli skorzystać z tego pytania. – War10ck

2

Wszystkie inne odpowiedzi nie są odpowiednie, ponieważ podział PHP zawsze będzie zwracać wartości float, jak wskazano wyraźnie w oficjalnym podręczniku PHP: Arithmetic Operators, z wyjątkiem przypadków, gdy dwa operandy są liczbami całkowitymi, które można równomiernie rozdzielić.

W rzeczywistości pytanie jest błędne: kod powinien wywołać 0.923 ..., jak oczekiwano od pytającego.

Sarkastycznie, odrzucona odpowiedź (pochodzi z @ BulletProof47) jest jedyną inną, która jest po prostu NIEPRAWDA (ale również bez znaczenia).Kto wie, co myślał, ale założę się, każdy wie, dlaczego został wybrany w dół: D

W przypadku, kto jest zainteresowany, podstawowa funkcja, która ma oddział w PHP jest div_function, z siedzibą w Zend/zend_operators.c, przedstawiono poniżej:

ZEND_API int div_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */ 
{ 
    zval op1_copy, op2_copy; 
    int converted = 0; 

    while (1) { 
     switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) { 
      case TYPE_PAIR(IS_LONG, IS_LONG): 
       if (Z_LVAL_P(op2) == 0) { 
        zend_error(E_WARNING, "Division by zero"); 
        ZVAL_BOOL(result, 0); 
        return FAILURE;   /* division by zero */ 
       } else if (Z_LVAL_P(op2) == -1 && Z_LVAL_P(op1) == LONG_MIN) { 
        /* Prevent overflow error/crash */ 
        ZVAL_DOUBLE(result, (double) LONG_MIN/-1); 
        return SUCCESS; 
       } 
       if (Z_LVAL_P(op1) % Z_LVAL_P(op2) == 0) { /* integer */ 
        ZVAL_LONG(result, Z_LVAL_P(op1)/Z_LVAL_P(op2)); 
       } else { 
        ZVAL_DOUBLE(result, ((double) Z_LVAL_P(op1))/Z_LVAL_P(op2)); 
       } 
       return SUCCESS; 
    ... 
Powiązane problemy