Discussione:
togliere la virgola
(troppo vecchio per rispondere)
alex
2009-12-01 09:19:20 UTC
Permalink
ho il numero 1,234 è voglio togliere la virgola per ottenere 1234.

Questo si può fare in vari modi, ad es.
x = "1,234".replace(",", "")

però non voglio usare funzioni stringa, ma soltanto funzioni prettamente
matematiche!!!

Ad es. potrei usare la funzione math.truncate, ma il problema è che
oltre alla virgola, toglie anche la parte decimale...
Matteo Migliore
2009-12-01 09:55:46 UTC
Permalink
Post by alex
però non voglio usare funzioni stringa, ma soltanto funzioni prettamente
matematiche!!!
Fai così:
---------------------------------
Const Number As Double = 1.234
Dim intPart = CInt(Fix(Math.Truncate(Number)))
Dim decimalPart = Number - intPart
Do While decimalPart - Math.Truncate(decimalPart) > 0
decimalPart *= 10
Loop

Dim fullNumber = intPart.ToString() & (CInt(Fix(decimalPart))).ToString()
---------------------------------

--
Matteo Migliore
http://blogs.ugidotnet.org/matteomigliore
alex
2009-12-01 11:12:24 UTC
Permalink
Post by Matteo Migliore
Post by alex
però non voglio usare funzioni stringa, ma soltanto funzioni
prettamente matematiche!!!
---------------------------------
Const Number As Double = 1.234
Dim intPart = CInt(Fix(Math.Truncate(Number)))
Dim decimalPart = Number - intPart
Do While decimalPart - Math.Truncate(decimalPart) > 0
decimalPart *= 10
Loop
Dim fullNumber = intPart.ToString() & (CInt(Fix(decimalPart))).ToString()
---------------------------------
moltiplicare il numero per 10 finchè non diventa intero, si!
Però in questo caso basterebbe moltiplicare direttamente per 1000, senza
andare per tentativi.
Ecco è proprio 1000 il numero (il moltiplicatore) che vorrei trovare, ma
tramite un calcolo matematico, in un sol colpo.
Insomma cerco una formula che se gli do in input 3.14, mi restituisca
100, se gli do 64,65441 mi restituisca 10000, ecc.

Ecco perchè sarebbe stato utile che vb.net implementasse una funzione
"TogliVirgola" che restituisse il numero senza virgola da mettere al
secondo membro dell'equazione che verrà costruita così:
3.14*x=TogliVirgola(3.14)
3.14*x=314
x=314/3.14
x=100
Stefano Ferrari
2009-12-01 12:14:53 UTC
Permalink
Post by alex
Ecco è proprio 1000 il numero (il moltiplicatore) che vorrei trovare, ma
tramite un calcolo matematico, in un sol colpo.
Insomma cerco una formula che se gli do in input 3.14, mi restituisca
100, se gli do 64,65441 mi restituisca 10000, ecc.
Dim number As Double
Dim moltiplicatore As Long
number = 1.23456789 'il tuo numero di esempio
moltiplicatore = 10 ^ CInt(Len(Decimal.Remainder(number, 1).ToString) - 2)

MessageBox.Show(moltiplicatore * number)

non conosco il framework quindi sicuramente c'è un metodo meno grezzo di
questo.

ciao
stefano
Matteo Migliore
2009-12-01 12:46:12 UTC
Permalink
Post by Stefano Ferrari
Dim number As Double
Dim moltiplicatore As Long
number = 1.23456789 'il tuo numero di esempio
moltiplicatore = 10 ^ CInt(Len(Decimal.Remainder(number, 1).ToString) - 2)
Non vuole usare metodi stringa :).

Senza moltiplicare per 10 non penso ci siano altri modi,
a meno di non usare Decimal.GetBits... ma probabilmente
non è perfomante e non è così facile da implementare.

--
Matteo Migliore
http://blogs.ugidotnet.org/matteomigliore
alex
2009-12-01 13:55:40 UTC
Permalink
Post by Matteo Migliore
Post by Stefano Ferrari
Dim number As Double
Dim moltiplicatore As Long
number = 1.23456789 'il tuo numero di esempio
moltiplicatore = 10 ^ CInt(Len(Decimal.Remainder(number, 1).ToString) - 2)
Non vuole usare metodi stringa :).
infatti, come ho visto quel Len :-b

Ad ogni modo intervenendo sul registro di windows il separatore decimale
si può personalizzare: invece della virgola, ad esempio si può impostare
"abc".
Quindi al posto di "1,23" si può avere "1abc23", per qui dovremo sostituire
Len(Decimal.Remainder(number, 1).ToString) - 2
con
Len(Decimal.Remainder(number, 1).ToString) - 5

Per questo *non voglio* basarmi sulle stringhe...
Matteo Migliore
2009-12-01 14:03:31 UTC
Permalink
Post by alex
Ad ogni modo intervenendo sul registro di windows il separatore decimale
si può personalizzare: invece della virgola, ad esempio si può impostare
"abc".
Non serve il registry di Windows :).

Se vuoi un sistema che funzioni comunque, basato sulle stringhe,
basta fare il ToString passando InvariantCulture, basta usare
il separatore definito li e risolvi tutti i problemi.

Altrimenti l'altro metodo che ti ho suggerito, vedi tu.

--
Matteo Migliore
http://blogs.ugidotnet.org/matteomigliore
alex
2009-12-02 10:11:07 UTC
Permalink
Post by Matteo Migliore
Post by alex
Ad ogni modo intervenendo sul registro di windows il separatore
decimale si può personalizzare: invece della virgola, ad esempio si
può impostare "abc".
Non serve il registry di Windows :).
si può anche fare dalle impostazioni internazionali, però mi pare che si
possa settare un solo carattere, non "abc"
Post by Matteo Migliore
Se vuoi un sistema che funzioni comunque, basato sulle stringhe,
basta fare il ToString passando InvariantCulture, basta usare
il separatore definito li e risolvi tutti i problemi.
Altrimenti l'altro metodo che ti ho suggerito, vedi tu.
si cmq non ci sono altri modi, userò il sistema del 10 ;)
Giovanni Dicanio
2009-12-02 19:02:06 UTC
Permalink
Post by alex
si cmq non ci sono altri modi, userò il sistema del 10 ;)
Che risulta una bella OverflowException se fai qualche test un po'
"impegnativo" per i double IEEE 754, tipo usando il semplice 1/3 :)

<code>
Const Number As Double = 1.0 / 3.0 ' 1.234
Dim intPart = CInt(Fix(Math.Truncate(Number)))
Dim decimalPart = Number - intPart
Do While decimalPart - Math.Truncate(decimalPart) > 0
decimalPart *= 10
Loop

Dim fullNumber = intPart.ToString() &
(CInt(Fix(decimalPart))).ToString()

MessageBox.Show(fullNumber)
</code>

Linguaggi moderni come VB tendono a far sembrare semplici le attività
programmatorie usando RAD etc., ma a volte avere un'idea precisa di alcuni
dettagli, come ad es. la rappresentazione in virgola mobile in formato IEEE
754 risulta utile.

Giovanni
Matteo Migliore
2009-12-02 21:14:00 UTC
Permalink
Post by Giovanni Dicanio
Che risulta una bella OverflowException se fai qualche test un po'
"impegnativo" per i double IEEE 754, tipo usando il semplice 1/3 :)
Hai ragione Giovanni, grazie per la precisazione.

--
Matteo Migliore
http://blogs.ugidotnet.org/matteomigliore
Matteo Migliore
2009-12-02 21:19:33 UTC
Permalink
A proposito dei bug causati dall'uso poco ponderato dei
valori in virgola mobile (come quello che ho scritto nell'esempio :()
c'è questo articolo, citato di recente dalla news letter di
Programmazione.it:
http://programmazione.it/index.php?entity=eitem&idItem=39997
http://www.techradar.com/news/computing/why-computers-suck-at-maths-644771?artc_pg=2

--
Matteo Migliore
http://blogs.ugidotnet.org/matteomigliore
Giovanni Dicanio
2009-12-03 09:13:56 UTC
Permalink
Post by Matteo Migliore
A proposito dei bug causati dall'uso poco ponderato dei
valori in virgola mobile [...]
I numeri in virgola mobile sono degli "oggetti" molto "interessanti" :)

Ad esempio, uno dei problemi che ho incontrato è che alcuni comparano i
numeri in virgola mobile usando l'operatore di uguaglianza (==), cioé, dati
x ed y variabili contenenti numeri in virgola mobile, scrivono codice tipo
if (x == y) ... . In realtà un test più corretto è quello di usare il valore
assoluto della differenza, e confrontarlo con una tolleranza, es. | x - y |
< toll.
(Infatti, secondo me il compilatore dovrebbe emettere per lo meno un warning
se trova dei double confrontati con ==).

Come letture interessanti, c'è un documento sul web intitolato qualcosa tipo
"What every computer scientist should know about floating-point arithmetic",
e vi sono anche dei post interessanti sul blog di Eric Lippert.

Giovanni
Mauro Servienti [MVP]
2009-12-03 09:19:05 UTC
Permalink
Ciao Giovanni,
Post by Giovanni Dicanio
Ad esempio, uno dei problemi che ho incontrato è che alcuni comparano i
numeri in virgola mobile usando l'operatore di uguaglianza (==), cioé, dati x
ed y variabili contenenti numeri in virgola mobile, scrivono codice tipo if
(x == y) ... . In realtà un test più corretto è quello di usare il valore
assoluto della differenza, e confrontarlo con una tolleranza, es. | x - y | <
toll.
sagace
Post by Giovanni Dicanio
(Infatti, secondo me il compilatore dovrebbe emettere per lo meno un warning
se trova dei double confrontati con ==).
interessante feedback. Che ne dici di girarlo al team?

.m
--
Mauro Servienti
{C67C0157-5D98-4733-A75E-93CAEE4BADC8}
Microsoft MVP - Visual C# / MCP
http://mvp.support.microsoft.com
http://blogs.ugidotnet.org/topics
whynot [ at ] topics [ dot ] it
Giovanni Dicanio
2009-12-03 09:52:44 UTC
Permalink
Ciao Mauro,
Post by Mauro Servienti [MVP]
Post by Giovanni Dicanio
(Infatti, secondo me il compilatore dovrebbe emettere per lo meno un
warning se trova dei double confrontati con ==).
interessante feedback. Che ne dici di girarlo al team?
Per me va bene.
:)

Giovanni
Giovanni Dicanio
2009-12-03 09:07:24 UTC
Permalink
Post by Matteo Migliore
Post by Giovanni Dicanio
Che risulta una bella OverflowException se fai qualche test un po'
"impegnativo" per i double IEEE 754, tipo usando il semplice 1/3 :)
Hai ragione Giovanni, grazie per la precisazione.
Di nulla.

Giovanni
alex
2009-12-03 13:42:03 UTC
Permalink
Post by Matteo Migliore
Post by Giovanni Dicanio
Che risulta una bella OverflowException se fai qualche test un po'
"impegnativo" per i double IEEE 754, tipo usando il semplice 1/3 :)
Hai ragione Giovanni, grazie per la precisazione.
da notare inoltre che ad ogni modo vb è proprio inadatto per certe cose,
e vengono fuori degli gravi errori logici.
Guardate qua:

Dim n As Double = (1018 - 10) / 990 '= 1.01818181818182 (14 cifre decimali)
Console.WriteLine(n)

While Math.Truncate(n) <> n
n *= 10
Console.WriteLine(n)
End While

Abbiamo un numero periodico, che come tutti i numeri periodici dovrebbe
avere infinite cifre decimali (altro che 14).
Un numero periodico quindi lo puoi moltiplicare per 10 quanto vuoi, ma
rimarrà sempre un decimale.
Per cui il ciclo While dovrebbe ripetersi all'infinito, cosa che non
accade...
Giovanni Dicanio
2009-12-04 08:52:05 UTC
Permalink
da notare inoltre che ad ogni modo vb è proprio inadatto per certe cose, e
vengono fuori degli gravi errori logici.
Dim n As Double = (1018 - 10) / 990 '= 1.01818181818182 (14 cifre decimali)
[...]
Abbiamo un numero periodico, che come tutti i numeri periodici dovrebbe
avere infinite cifre decimali (altro che 14).
Un numero periodico quindi lo puoi moltiplicare per 10 quanto vuoi, ma
rimarrà sempre un decimale.
Per cui il ciclo While dovrebbe ripetersi all'infinito, cosa che non
accade...
Non è VB ad essere inadatto!
Comportamenti del genere si verificherebbero anche in C, C++, C# e qualsiasi
linguaggio che usi lo standard IEEE 754 per rappresentare i numeri in
virgola mobile.

Un numero periodico (così come un numero trascendente come pi greco, o la
'e' di Nepero, etc.) *non* è rappresentabile in maniera esatta e completa
usando numeri in virgola mobile nel formato IEEE 754.
IEEE 754 è un *modello* di un concetto matematico astratto (il numero
"reale"), e come ogni modello esso è una rappresentazione *parziale*
dell'ente che si vuole modellare.

Se vuoi, mettila in questi termini: il computer ha dei registri (ed una
memoria) *finita*, quindi non puoi rappresentare infinite cifre decimali.

In certi casi, si potrebbe pensare di rappresentare un numero periodico
(come ad es. 1/3 = 0,3333....) non come numero in virgola mobile, ma con la
sua frazione generatrice.
Ovvero, si potrebbe definire una classe ad es. 'NumeroRazionale', costituita
da un paio di data member interi: 'Numeratore' e 'Denominatore'.
In tal caso, 1/3 non vorrebbe rappresentato come 0,333....3 troncato, ma
semplicemente come la coppia di interi 1 (numeratore) e 3 (denominatore).
Poi si potrebbero definire per questa classe operatori di somma, differenza,
etc. (le classiche operazioni con le frazioni che si imparano alla scuola
media inferiore, per intenderci).
E magari anche un metodo ToDouble(), che esegue semplicemente il rapporto
Numeratore/Denominatore, ritornando un double IEEE 754 (però in questo caso
si abbandonerebbe la precisione "esatta" data dalle frazioni, e si
passerebbe a quella approssimata tipica dei double).
(Ma ovviamente tale sistema non è applicabile ad esempio a pi greco, che è
un numero reale ma non un numero razionale.)

Giovanni
alex
2009-12-05 09:59:26 UTC
Permalink
Post by Giovanni Dicanio
In certi casi, si potrebbe pensare di rappresentare un numero periodico
(come ad es. 1/3 = 0,3333....) non come numero in virgola mobile, ma con
la sua frazione generatrice.
Ovvero, si potrebbe definire una classe ad es. 'NumeroRazionale',
costituita da un paio di data member interi: 'Numeratore' e 'Denominatore'.
In tal caso, 1/3 non vorrebbe rappresentato come 0,333....3 troncato, ma
semplicemente come la coppia di interi 1 (numeratore) e 3 (denominatore).
infatti, invece del numero ci si può portare dietro il "generatore"
Marcello Cantelmo
2009-12-02 23:53:38 UTC
Permalink
Post by alex
ho il numero 1,234 è voglio togliere la virgola per ottenere 1234.
Questo si può fare in vari modi, ad es.
x = "1,234".replace(",", "")
però non voglio usare funzioni stringa, ma soltanto funzioni prettamente
matematiche!!!
Ad es. potrei usare la funzione math.truncate, ma il problema è che
oltre alla virgola, toglie anche la parte decimale...
qui una semplice variante utilizzando i *decimal* e senza *nessuna*
funzione string:


Dim value As Decimal = -(1.0 / 7.0) '-12.345
Dim tmp As Decimal = (Math.Abs(value) - Math.Floor(Math.Abs(value)))
Dim size As Integer = -1
'<<<
If tmp > 0 Then
Do
size += 1
tmp = ((tmp - Math.Floor(tmp)) * 10)
Loop While (tmp > 0)
Else
size = 1
End If
'<<<
Dim newValue As Decimal = (value * (10 ^ size))


HTH
--
Marcello Cantelmo
www.cantelmosoftware.com
Continua a leggere su narkive:
Loading...