2012-09-13 17 views
5

Sto costruendo una calcolatrice con BSP. Come ho provato con vari numeri, mi sono imbattuto in un problema che i numeri decimali non vengono visualizzati correttamente.58.85 visualizza come 58.84999999999

Ad esempio. 58,85 -> 58,849999. Ma 58.84 o 58.86 funzionano bene. 58.8471 -> 54.84710000000001. Alla fine, l'ultima cifra digitata verrà salvata dal nulla.

Il mio codice seguente di seguito.

method GENERATE_NUM. 

    DATA: lv_digi type I. * number of digits after the decimal point 


    call METHOD me->get_decimal 
    RECEIVING 
     getdigits = lv_digi. 

    *if it is a natural number 
    IF lv_digi = 0. 
    IF thisnum < 0. 
     result = thisnum * 10 - newdigit. 
    ELSE. 
     result = thisnum * 10 + newdigit. 
    ENDIF. 

    *if it is a float number 
    Else. 
    IF thisnum < 0. 
     result = thisnum - (newdigit/10 ** lv_digi). 
    ELSE. 
     result = thisnum + (newdigit/10 ** lv_digi). 
    ENDIF. 

    *increase the number of decimal point by 1 
    call method me->set_decimal. 
    ENDif. 

endmethod. 

Quello che fondamentalmente faccio è ogni volta un numero viene cliccato, si chiama il metodo "generate_num". Richiede THISNUM, NEWDIGIT, RESULT come parametri.
thisnum = numero corrente (es .: 58.8)
newdigit = numero cliccato (es .: 5)
risultato = numero generato (atteso: 58,85 ma restituisce 58,849999).

+1

http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html – Mysticial

+0

Sarebbe utile illustrare dove e come risolvere questo problema? –

+0

È una di quelle domande più frequenti che richiedono una spiegazione molto lunga. Lascerò che qualcun altro intervenga o trovi un duplicato adatto per chiuderlo. – Mysticial

risposta

7

Quando si desidera che i numeri decimali con precisione fissa, è necessario utilizzare il tipo P (numero di riempimento) anziché float.

Esempio:

DATA lv_fixed_point TYPE p LENGTH 16 DECIMALS 2. 

Questo crea una variabile in virgola fissa con due cifre dopo il punto. Il significato esatto del parametro "lunghezza" non è così diretto. Dal documentation:

numeri Pranzo - tipo P

Tipo dati P permette cifre dopo la virgola. Il numero di posizioni decimali è generico ed è determinato nel programma. L'intervallo di valori di tipo P del valore dipende dalla sua dimensione e dal numero di cifre dopo il punto decimale. La dimensione valida può essere qualsiasi valore compreso tra 1 e 16 byte. Due cifre decimali sono raggruppate in un byte, mentre l'ultimo byte contiene una cifra e il segno. Sono consentite fino a 14 cifre dopo il punto decimale. Il valore iniziale è zero. Quando si lavora con i dati di tipo P , è una buona idea impostare l'attributo del programma Fixed aritmetico punto .In caso contrario, i numeri P di tipo vengono trattati come numeri interi.

È possibile utilizzare i dati di tipo P per valori quali le distanze, i pesi, gli importi di denaro e così via.

+0

semplicemente cambiando il tipo per risolvere il mio problema. Grazie mille. –

0

Oppure è possibile chiamare CALL FUNCTION 'FLOATINGPOINT_COMPARE_ABSOLUTE' in formato epsilon float IEEE. Lavorare con virgola mobile si dovrebbe effettivamente evitare di utilizzare direttamente i confronti, e scrivere il proprio con Epsilon built-in:

IS_EQUAL 
IS_GREATER 
IS_GREATER_EQUAL 
IS_LESS 
IS_LESS_EQUAL 

sono il minimo indispensabile.

Altre informazioni about floating point here.

Imparalo. Vivilo. Lo adoro.

Come un esercizio non banale si può anche leggere su NaN+Inf e -Inf (anche Snan se si lavora con altri tipi DECFLOAT invece di f).

+0

Ma impacchettato può essere la soluzione ottimale (ma non così veloce dato che sono ancora interpretati come CHAR-kinda) con il minimo di ostacoli. – Marius