Italian trasformare un importo in un intero

fabio_linate_milano

Member
Licensed User
Longtime User
Salve a tutti

Nel realizzare un'applicazioncina ho avuto la necessità di memorizzare degli importi in un db SQLite. Ho pensato di definire il campo (della tabella sqlite) come intero quindi moltiplicare gli importi * 100 e registrali nel DB per poi dividerli per 100 quando vado a ripescarli dal db.
Nel fare questo mi sono imbattuto in una cosa curiosa
B4X:
    Dim l As Long
    Dim d As Double
   
    'l = EditText1.Text * 100
    'd = EditText1.Text
    d = 1250.60
    'd = 1250.61
    'd = 3900.60
    'd = 8250.59
    l = d * 100
    Msgbox(l, "")

quando d vale 1250.60 moltiplicato * 100 fornisce 125059 !!!!!
una spiegazione per l'arcano?

un saluto

p.s. provare per credere
 

LucaMs

Expert
Licensed User
Longtime User
Anche se mi fido, non posso non volerlo vedere coi miei occhi, perché è piuttosto grave, ergo... provo...

Ovviamente, hai ragione.

Non c'è che da chiedere ad Erel, perché io non vedo come questo non possa non essere considerato un grosso bug.

Anzi, grazie per la segnalazione.
 

fabio_linate_milano

Member
Licensed User
Longtime User
Ma comunque è proprio così
non sto prendendo fischi per fiaschi data l'ora tardi
prima di portare avanti la cosa non vorrei fare figuracce
 

LucaMs

Expert
Licensed User
Longtime User
No, no, confermo, è esattamente così.

Mi sono messo a cercare funzioni di conversione; ho trovato questa, la cui descrizione, sarà il mio pessimo inglese, ma io trovo assurda:
B4X:
Dim D As Double = 1250.60
Dim L As Long = Ceil(d * 100)
Log("L =: " & L)

upload_2015-10-5_0-48-13.png


Io traduco così:
"Restituisce il più piccolo double che sia maggiore o uguale al numero specificato e uguale ad un intero"

Ma sempre nella "firma" sembra restituire un Double.


In questo caso, comunque, restituisce 125060
 
Last edited:

LucaMs

Expert
Licensed User
Longtime User
Il problema è che fanno schifo i calcoli con i double:

B4X:
Dim D As Double = 1250.60
D = D * 100
Dim L As Long = D ' * 100
Log("D = " & D)
Log("L =: " & L)

log:
D = 125059.99999999999
L =: 125059


D viene calcolata male, l'assegnazione a L tronca i decimali, non arrotonda.
 
Last edited:

cimperia

Active Member
Licensed User
Longtime User
questo è il modo in cui funziona in Java

Se si esegue questo codice Java, il output sarà 125059.

Provate voi stessi on line: jdoodle
---
That's the way it works in Java

If you run this java code, the output will be 125059.

Try it yourself on line: jdoodle

B4X:
public class MyClass {

   public static void main(String args[]) {
   double d = 1250.60;
   long l = (long)(d*100);

   System.out.println(l);

  }
}
Edit: Added Italian translation to satisfy Luca ;)
 
Last edited:

cimperia

Active Member
Licensed User
Longtime User
(siamo nel forum italiano, @cimperia ;))[/QUOTE]

Ho modificato il mio post :p
 

moster67

Expert
Licensed User
Longtime User
Come diceva @cimperia, questo comportamento è normale in java e non è un bug. Quando si converte da tipi dei dati con decimali (float e double) a long, int, la parte a destra viene semplicemente troncato. Questo esempio mostra bene la questione:

B4X:
Dim l As Long
Dim d As Double
d = 1250.60
d = 1250.60 * 100 '=125059.99999999999
l = d 'il valore 125059.99999999999 -> 125059 - decimali vengono troncati
Log(l) ' = 125059

Quando si studia java, quasi tutti i testi insegnano questi ingippi/pericoli. Non succede solo in java ma anche in c++ etc..

In ogni caso, sarebbe carino se l'IDE era in grado di emettere un "warning" per conversioni dei dati di questi casi (sarebbe solo da capire se l'IDE riesce a capire il "pericolo" prima che il codice viene compilato o no).
 
Last edited:

moster67

Expert
Licensed User
Longtime User
dovrebbe essere sufficiente usare la funzione Round per risolvere..

Round (Number As Double) As Long
Returns the closest long number to the given number.
 

fabio_linate_milano

Member
Licensed User
Longtime User
grazie per il feedback

Per fare una battuta diciamo che l'email piuttosto che indirizzarla ad Erel sarebbe meglio mandarla a Larry Ellison!!!!
Non conosco bene Java (per diletto ho iniziato a studiarlo proprio in questo periodo), ho fatto la prova che suggerisce cimperia

upload_2015-10-5_11-7-10.png


è vero. La cosa mi lascia un po' sbigottito (per non dire altro)
Non definirlo un bug questa cosa qui non sono molto d'accordo.
Da notare che nel codice Java definisco le costanti in modo coerente (nessun cast quindi per convertire i tipi)
deduco quindi che in Java
1250.6 * 100 in float è uguale a 125060
1250.6 * 100 in double è uguale a 125059.9(periodico)
!!!!!!!!!!!!!!!!

un saluto
 

LucaMs

Expert
Licensed User
Longtime User
Appunto; il codice:
B4X:
Dim D As Double = 1250.60
D = D * 100
Log("D = " & D)

non include casting (che, tra l'altro, in B4A dovrebbero essere automatici) né, quindi, troncamenti.
Il risultato è... SEMPLICEMENTE... D = 125059.99999999999, ovvero sbagliato!
 

sirjo66

Well-Known Member
Licensed User
Longtime User
Come altri hanno detto è un problema comune di tanti linguaggi, poiché il tutto nasce da come i microprocessori gestiscono i valori double, e cioè la mantissa e l'esponente.
Per certi valori infatti è quasi impossibile rappresentare un valore double perfettamente tramite mantissa ed esponente, e da qui nasce il problema degli arrotondamenti.

Sergio
 

LucaMs

Expert
Licensed User
Longtime User
Uhm... è un bel po' che non programmo in VB.Net, ma non mi pare di aver mai avuto quei problemi.

Capisco arrotondamenti, "precisione" etc. ma suppongo che quelle due righe di codice che ho scritto nel post #13 darebbero il risultato voluto, in VB.Net.

Anzi, dato che "so' de coccio", benché VB.Net impieghi mezza giornata ad avviarsi :D, una provoletta la faccio subitosto.
 

udg

Expert
Licensed User
Longtime User
La "stranezza", come già detto, non è poi tale se consideriamo che la rappresentazione di un numero decimale in binario non può essere esatta.
In fondo anche nel nostro "perfetto" mondo decimale abbiamo difficoltà a rappresentare completamente il risultato di 10/3 senza ricorerre a "strani" trattini..eheh

Nel caso presentato, il problema sta evidentemente nella rappresentazione binaria di 1250.60 che diviene 1250.59999.. e quindi moltiplicato per 100 diventa 125059.999..
Alcune interessanti letture:
https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html

ma soprattutto
https://docs.oracle.com/javase/8/docs/api/java/math/BigDecimal.html
http://developer.android.com/reference/java/math/BigDecimal.html
per gestire le cose come avrebbe voluto fare Fabio sin dall'inizio.
 

LucaMs

Expert
Licensed User
Longtime User
Scusi, signor UDG :)

ma a me sviluppatore b4a non interessa molto la rappresentazione (interna) binaria. Inoltre, la precisione di un Double dovrebbe essere più che sufficiente per un decimale a due cifre.

Resta il fatto che facendo girare l'esempio in VB.Net non ci sono problemi, risultato perfetto, in B4A no. PER ME E' SOLO UN BUG (non so se sia dovuto a Java o B4A).


[ho allegato... di là... qualcosa che potrebbe interessarti, benché semplice, non inerente a tutto ciò]
 

maXim

Active Member
Licensed User
Longtime User
... le differenze, come in questo caso, tra Double e Float sono conosciute da molti e da lungo tempo, tanto è vero che ormai anche io da qualche anno ho smesso di disquisire su questo problema visto che ogni volta rischiavo di penetrare in una polemica senza fine... alcuni anni fa, quando realizzai la classe fMATH per la libreria db2000.B4x.eXtrafunctions, ero indeciso su cosa inventarmi per "normalizzare" in maniera corretta il problema degli arrotondamenti e/o dei troncamenti di alcuni risultati delle operazioni aritmetiche... per i miei scopi processare i risultati in una sequenza di calcoli e confronti con floor, ceil, round, rint, ecc. non aveva molto senso e, a dire il vero, non rientrava nella mia logica (ero, ma lo sono ancora, acerbo in Java) e pertanto creai dei metodi del tutto simili alle funzioni che ero abituato ad utilizzare e che oggi ritroviamo anche nei compilatori B4x, visto che c'ero inclusi nella libreria anche Fix... so benissimo che la libreria non è niente di eccezionale ma, a dire il vero, ancora oggi la utilizzo con soddisfazione...;)
 
Top