& # 8220; intelligente & # 8221; cast di doppie o due stringhe diversamente formattate?
-
06-07-2019 - |
Domanda
Sto lavorando con un database che ha il limite che il solo tipo di dati (numerico) che può memorizzare è un doppio . Quello che voglio fare è scegliere il numero per una determinata riga e inserirlo in una richiesta HTTP. Il problema ruota attorno al fatto che non posso sapere se questo numero dovrebbe o non dovrebbe avere decimali.
Ad esempio, se il doppio è un ID, non posso avere alcun tipo di formattazione, poiché il sito che riceve la richiesta HTTP sarà confuso. Osservare i seguenti esempi:
site.com/showid.php?id=12300000 // OK
site.com/showid.php?id=1.23E7 // Bad; scientific notation
site.com/showid.php?id=12300000.0 // Bad; trailing decimal
La soluzione a questo sarebbe di lanciarlo in un lungo . Ignorando il problema di traboccare il lungo, risolve la notazione scientifica e (ovviamente) il decimale finale. Questa potrebbe essere una soluzione accettabile, ma sarebbe bello se il codice non presupponesse che si trattasse di ID. E se, ad esempio, dovessi interrogare un sito che mostra una mappa e il numero sono coordinate, dove i decimali sono molto importanti? Quindi un cast lungo non è più accettabile.
In breve;
- Se il doppio non ha decimali, non aggiungere un decimale finale.
- Se ha decimali, conservali tutti.
- Nessuno dei due casi dovrebbe avere una notazione scientifica o migliaia di separatori.
Questa soluzione verrà trasferita su C # e Java, quindi accetto le risposte in entrambe le lingue. (Oh, e non avevo idea di come chiamare questa domanda, sentiti libero di rinominare se hai qualcosa di meglio.)
Soluzione 6
Ecco la mia conclusione:
- Verifica se il doppio ha decimali.
- A seconda di ciò, formattare la stringa di conseguenza.
-
E poi qualcosa di importante; senza specificare una cultura invariante, la virgola nel caso dei decimali può essere un "," anziché un ". " che non piace alle richieste HTTP. Naturalmente, questo problema si presenta solo se il tuo sistema operativo è impostato su una lingua che preferisce la virgola.
public static string DoubleToStringFormat(double dval) { long lval = (long)dval; if ((double)lval == dval) { // has no decimals: format as integer return dval.ToString("#.", CultureInfo.InvariantCulture); } else { // has decimals: keep them all return dval.ToString("0.##################", CultureInfo.InvariantCulture); } }
Altri suggerimenti
Per completare la risposta di gustafc (che mi ha battuto di 1 minuto), ecco la riga di codice pertinente per C #:
MyDouble.ToString("0.################")
o
string.Format("{0:0.################}", MyDouble);
Poiché è sicuro formattare il valore senza zero finali se è integrale (sia che rappresenti un ID o una coordinata), perché non codificare semplicemente la logica che descrivi nei tuoi punti elenco? Ad esempio (C #, ma dovrebbe tradursi prontamente in Java):
// Could also use Math.Floor, etc., to determine if it is integral
long integralPart = (long)doubleValue;
if ((double)integralPart == doubleValue)
{
// has no decimals: format it as an integer e.g. integralPart.ToString("D") in C#
}
else
{
// has decimals: keep them all e.g. doubleValue.ToString("F17")
}
Che ne dici di incapsulare il numero in un tipo personalizzato?
public class IntelligentNumber
{
private readonly double number;
public IntelligentNumber(double number)
{
this.number = number;
}
public override string ToString()
{
long integralPart = (long)this.number;
if((double)integralPart == this.number)
{
return integralPart.ToString();
}
else
{
return this.number.ToString();
}
}
}
Vedi anche la risposta di Vilx- per un algoritmo migliore di quello sopra.
controlla se num == round (num)
In Java, puoi farlo con DecimalFormat .
static String format(double n) {
return new DecimalFormat("0.###########################").format(n);
}
I segnaposto #
non verranno visualizzati a meno che il numero sia diverso da zero da inserire lì e il punto decimale non venga visualizzato a meno che non ci sia qualcosa che lo segue.