Visualizzazione dei risultati da 1 a 10 su 10
  1. #1
    Utente di HTML.it L'avatar di strae
    Registrato dal
    Apr 2008
    Messaggi
    407

    Io con questi cavolo di decimali non ci capisco più niente.

    O sono io che faccio casino, o c'è qualcosa che non quadra con php e i decimali.

    Perchè una cosa del genere
    Codice PHP:
    $a 247.715;
    echo 
    number_format($a20); 
    mi restituisce 247.71500000000003183231 invece che 247.71500000000000000000 ??

    C'è un qualche parametro da settare?
    You HAVE to assume your visitor is a maniac serial killer, out to destroy your application. And you have to prevent it.
    I can accept failure, everyone fails at something - But I can't accept not trying.

  2. #2

  3. #3
    Utente di HTML.it L'avatar di strae
    Registrato dal
    Apr 2008
    Messaggi
    407
    Originariamente inviato da filippo.toso
    Sei tu che non hai mai letto il manuale:

    http://php.net/manual/en/language.types.float.php
    Si ok, la precisione del float è di 14 decimali, ammetto che non avevo letto quella pagina..
    A me però ne servono solo 6, o meglio, 2 quando stampo il numero.

    Spiegami perchè i decimali di questi due numeri sono diversi:

    Codice PHP:
    $primo number_format(2.7152'.''');
    var_dump($primo);
    //string(4) "2.7[b]2[/b]"
    $secondonumber_format(262.7152'.''');
    var_dump($secondo); 
    //string(6) "262.7[b]1[/b]" 
    Ho notato che con qualsiasi numero < 256 l'approssimazione dei decimali 0.715 la restitiusce come 0.72 (approssima quel 0.005 in eccesso, come è giusto che sia d'altronde).

    Se invece il numero è maggiore di 256, considera lo 0.005 in difetto, restituendo 0.71.

    Questo mi causa un bel pò di problemi, per delle semplici somme:

    Codice PHP:
    $a 163.2;
    $b 32.4;
    $c 14.4;
    $d 50;
    $e 2.715;

    $a_stampa number_format($a2',''');
    $b_stampa number_format($b2',''');
    $c_stampa number_format($c2',''');
    $d_stampa number_format($d2',''');
    $e_stampa number_format($e2',''');

    //number_format restituisce delle stringhe.
    printf("Sommo %s + %s + %s + %s + %s"$a_stampa$b_stampa$c_stampa$d_stampa$e_stampa);

    $somma $a $b $c $d $e;
    $somma_stampa number_format($somma2',''');
    printf("
    Il risoltato: %s"
    $somma_stampa);

    //Output:
    //Sommo 163,20 + 32,40 + 14,40 + 50,00 + 2,72
    //Il risoltato: 262,71 
    Quel 0.715 è un problema.
    Perchp se l'intero è < 256 lo arrotonda correttamente, altrimenti in difetto!?
    You HAVE to assume your visitor is a maniac serial killer, out to destroy your application. And you have to prevent it.
    I can accept failure, everyone fails at something - But I can't accept not trying.

  4. #4
    Originariamente inviato da strae
    Si ok, la precisione del float è di 14 decimali, ammetto che non avevo letto quella pagina..
    Guarda che è meglio se la rileggi di nuovo, perchè non hai ancora capito cosa implica la numerazione binaria a virgola mobile nei numeri decimali.

  5. #5
    Utente di HTML.it L'avatar di strae
    Registrato dal
    Apr 2008
    Messaggi
    407
    Originariamente inviato da filippo.toso
    Guarda che è meglio se la rileggi di nuovo, perchè non hai ancora capito cosa implica la numerazione binaria a virgola mobile nei numeri decimali.
    Se intendi questo

    Warning
    Floating point precision

    It is typical that simple decimal fractions like 0.1 or 0.7 cannot be converted into their internal binary counterparts without a small loss of precision. This can lead to confusing results: for example, floor((0.1+0.7)*10) will usually return 7 instead of the expected 8, since the internal representation will be something like 7.9.

    This is due to the fact that it is impossible to express some fractions in decimal notation with a finite number of digits. For instance, 1/3 in decimal form becomes 0.3.

    So never trust floating number results to the last digit, and never compare floating point numbers for equality. If higher precision is necessary, the arbitrary precision math functions and gmp functions are available.
    l'ho letto e credo di averlo anche capito, i numeri float non sono affidabili.


    Allora rigiro il problema, come faccio ad avere dei calcoli affidabili usando 6 decimali?
    La prima 'soluzione' che mi è venuta in mente è di usare solo gli interi.
    Moltiplico ogni numero per 1000000, e uso quel valore per fare tutti i calcoli.. solo quando devo stampare il valore all'utente lo 'riformatto' dividendolo per 1000000, mettendo la virgola, etc.
    Ma mi sembra qualcosa di orribile
    You HAVE to assume your visitor is a maniac serial killer, out to destroy your application. And you have to prevent it.
    I can accept failure, everyone fails at something - But I can't accept not trying.

  6. #6
    Originariamente inviato da strae
    l'ho letto e credo di averlo anche capito, i numeri float non sono affidabili.
    L'affermazione [i]"i numeri float non sono affidabili"[i] è piuttosto lontana dalla realtà, comunque ...
    Originariamente inviato da strae
    come faccio ad avere dei calcoli affidabili usando 6 decimali?
    E dire che sarebbe sufficiente leggere quanto viene suggerito ...

    http://php.net/manual/en/language.types.float.php

    f higher precision is necessary, the arbitrary precision math functions and gmp functions are available.

  7. #7
    Utente di HTML.it L'avatar di strae
    Registrato dal
    Apr 2008
    Messaggi
    407
    Guarda che li ho provati subito sia bc che gmp, ma il risultato è lo stesso.

    Ora però mi sono accorto di una cosa, probabilmente non è il calcolo ad essere sbagliato, ma la formattazione.

    Potrebbe essere number_format() che a volte l'approssimazione del 5 finale la fà in eccesso e a volte in difetto?
    You HAVE to assume your visitor is a maniac serial killer, out to destroy your application. And you have to prevent it.
    I can accept failure, everyone fails at something - But I can't accept not trying.

  8. #8
    Originariamente inviato da strae
    Guarda che li ho provati subito sia bc che gmp, ma il risultato è lo stesso.
    A me funzionano perfettamente ...

    Codice PHP:
    <?php 
    $a 
    '0.715';
    for (
    $i 0$i 1000$i++) {
        echo(
    bcadd($i$a2) . '
    '
    );
    }
    ?>

  9. #9
    Utente di HTML.it L'avatar di strae
    Registrato dal
    Apr 2008
    Messaggi
    407
    Originariamente inviato da filippo.toso
    A me funzionano perfettamente ...

    Codice PHP:
    <?php 
    $a 
    '0.715';
    for (
    $i 0$i 1000$i++) {
        echo(
    bcadd($i$a2) . '
    '
    );
    }
    ?>
    Ehm.. no, non è che funziona, anzi.. così tronca il 3° decimale, non fà l'arrotondamento...

    A me serve che faccia l'arrotondamento (e tutto il problema nasce forse da qui)

    Cioè X.715 deve diventare X.72, sempre e comunque.
    Invece number_format() mi esegue l'arrotondamento in eccesso (come sia giusto che sia, visto che l'ultima cifra è 5) per numeri < 256, in difetto per numeri > 256.

    Poi facendo dei test torna a essere in eccesso sopra il 326 mi pare, e così via..

    Guarda l'output del tuo codice usando number_format (ho messo scale=3 perchè non voglio il troncamento ma l'arrotondamento):

    Codice PHP:
    <?php
    $a 
    0.715;
    for (
    $i 0$i 1000$i++) {
        
    $k bcadd($i$a2);
        echo 
    number_format($k2) . '
    '
    ;
    }
    ?>
    Se noti, da 256 a 326 restituisce X.71, invece per tutti gli altri numeri X.72

    Ho anche provato a farlo ciclare fino a 10000, il 'problema' sembra essere solo nella fascia 256-326.

    Se invece di 0.715 utilizziamo 0.716, il problema non si pone, arrotonda sempre in eccesso...

    A questo punto, mi sembra di aver capito che il punto della questione è number_format(), e non la somma o il float (nell'esempio da te postato, togliento bcadd e mettendo la somma normale +, l'output è lo stesso)
    You HAVE to assume your visitor is a maniac serial killer, out to destroy your application. And you have to prevent it.
    I can accept failure, everyone fails at something - But I can't accept not trying.

  10. #10
    Utente di HTML.it L'avatar di strae
    Registrato dal
    Apr 2008
    Messaggi
    407
    Dopo altri test mi sento di confermare che il calcolo con i float era giusto (anche senza librerie bc o gmp, non facevo certo calcoli molto complessi o con molti decimali), e il problema l'ho risolto evitando di utilizzare number_format e scrivendo una funzione apposita


    Edit: però davvero non capisco, sembra che l'errore venga fuori solo con la esatta combinazione dei decimali: 0.715

    Ho provato con altre combinazioni (0.815, 0.475, 0.615, etc..) ma nada.
    You HAVE to assume your visitor is a maniac serial killer, out to destroy your application. And you have to prevent it.
    I can accept failure, everyone fails at something - But I can't accept not trying.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.