2010-07-19 16 views
8

Abbiamo un problema interessante in cui è necessario determinare la precisione decimale di un input utente (casella di testo). Essenzialmente dobbiamo conoscere il numero di cifre decimali inseriti e poi restituire un numero di precisione, questo è meglio illustrato con esempi:Determinare la precisione decimale di un numero di input

4500 inserito produrrà un risultato 1
4500,1 inserito produrrà un risultato 0,1
4500.00 inserito sarà fornire un risultato 0,01
4500.450 immesso produrrà un risultato 0,001

Stiamo pensando di lavorare con la stringa, trovare il separatore decimale e quindi calcolare il risultato. Mi chiedo solo se esiste una soluzione più semplice a questo.

+3

Sei sicuro che 4500 sarebbe un 1 e non un 100? – corsiKa

+0

Qual è il risultato previsto nel caso 0.0 e 0.1? – user1785960

+0

Per me è una domanda confusa. Non chiedi precisione decimale. Chiedi: come ottenere il numero di cifre in una parte della frazione. La definizione di 'decimal precision' è qui per Me: https://docs.oracle.com/cd/B28359_01/server.111/b28318/datatype.htm#i16209 – user1785960

risposta

8

Dal momento che gli ultimi esempi indicano che gli zeri finali sono significativi, escluderei qualsiasi soluzione numerica e andrei per le operazioni con le stringhe.

3

No, non esiste una soluzione più semplice, è necessario esaminare la stringa. Se converti "4500" e "4500.00" in numeri, entrambi diventano il valore 4500 in modo che non sia possibile sapere quante cifre senza valore ci fossero dietro il separatore decimale.

1

Lavorare con la stringa è abbastanza semplice.

Se non c'è "." nella stringa, restituire 1.

Altrimenti restituire "0", seguito da n-1 "0", seguito da un "1", dove n è la lunghezza della stringa dopo il punto decimale.

+0

Attenzione: prima assicurati che la stringa sia un numero valido/la l'ultimo carattere non è un "." – luiscubal

9

Basta chiedersi se esiste una soluzione più semplice a .

No.

Usa stringa:

string[] res = inputstring.Split('.'); 
int precision = res[1].Length; 
+15

Il carattere da dividere deve essere il separatore decimale corretto - [NumberFormatInfo.NumberDecimalSeparator] (http://msdn.microsoft.com/en-us/library/system.globalization.numberformatinfo.numberdecimalseparator.aspx) – ChrisF

14

penso che si dovrebbe fare solo quello che lei ha suggerito - utilizzare la posizione del punto decimale. Ovvio svantaggio potrebbe essere che devi pensare a internatialisation te stesso.

var decimalSeparator = NumberFormatInfo.CurrentInfo.CurrencyDecimalSeparator; 

var position = input.IndexOf(decimalSeparator); 

var precision = (position == -1) ? 0 : input.Length - position - 1; 

// This may be quite unprecise. 
var result = Math.Pow(0.1, precision); 

C'è un'altra cosa che si potrebbe provare - i Decimal tipo memorizza un valore precission interna. Pertanto è possibile utilizzare Deciml.TryParse() e ispezionare il valore restituito. Forse l'algoritmo di parsing mantiene la precessione dell'input.

Infine vorrei suggerire di non provare qualcosa utilizzando numeri in virgola mobile. Basta analizzare l'input per rimuovere qualsiasi informazione sugli zero finali. Quindi devi aggiungere una cifra artificiale diversa da zero per conservarli o fare trucchi simili. Potresti imbatterti in problemi di precisioni. Infine, trovare la precisione basata su un numero in virgola mobile non è semplice. Vedo qualche brutta matematica o un ciclo moltiplicato con dieci ogni iterazione fino a quando non c'è più alcuna parte frazionaria. E il ciclo è dotato di nuove emissioni precission ...

UPDATE

Analisi in una fabbrica deciaml. Se Decimal.GetBits() per i dettagli.

var input = "123.4560"; 

var number = Decimal.Parse(input); 

// Will be 4. 
var precision = (Decimal.GetBits(number)[3] >> 16) & 0x000000FF; 

Da qui utilizzando Math.Pow(0.1, precision) è semplice.

+0

+1 per decimal.Precision, non avevo idea che potesse farlo :) Vedi http://stackoverflow.com/questions/1132765/adjusting-decimal-precision-net –

+1

Poiché l'OP chiedeva "una soluzione più semplice", e forse dedotta " prestazioni migliori ", in che modo questo confronta le prestazioni con l'analisi della stringa? –

+0

Grazie per questo! –

2

Come interessante, lo Decimal tenta di mantenere la precisione immessa dall'utente. Ad esempio,

Console.WriteLine(5.0m); 
Console.WriteLine(5.00m); 
Console.WriteLine(Decimal.Parse("5.0")); 
Console.WriteLine(Decimal.Parse("5.00")); 

Ha uscita:

5.0 
5.00 
5.0 
5.00 

Se la vostra motivazione nel monitoraggio la precisione dell'ingresso è puramente per motivi di ingresso e di uscita, questo può essere sufficiente per affrontare il problema.

+0

Vedere la risposta di Daniel Bruckner su come accedere direttamente a queste informazioni. – Brian

1

Ecco una possibile soluzione utilizzando stringhe;

static double GetPrecision(string s) 
{ 
    string[] splitNumber = s.Split('.'); 
    if (splitNumber.Length > 1) 
    { 
     return 1/Math.Pow(10, splitNumber[1].Length); 
    } 
    else 
    { 
     return 1; 
    } 
} 

C'è una domanda qui; Calculate System.Decimal Precision and Scale che sembra che potrebbe essere di interesse se si desidera approfondire ulteriormente questo.

+1

È necessario utilizzare [NumberFormatInfo.NumberDecimalSeparator] (http://msdn.microsoft.com/en-us/library/system.globalization.numberformatinfo.numberdecimalseparator.aspx) per ottenere il separatore decimale corretto per la locale. – ChrisF

+0

Cool, grazie per il suggerimento. –

Problemi correlati