Conversione di una stringa vuota in un numero [chiuso]

1

Se si sta progettando una funzione che dovrebbe convertire una stringa in un intero, come si converte una stringa vuota? La domanda riguarda solo questo particolare valore di input (stringa vuota).

Tra il lancio di un'eccezione ExcStringIsEmpty e la conversione in 0 opzioni preferisco la prima. Sembra più logico per me. Perché quando esegui una conversione opposta dal valore intero 0 difficilmente lo converti in una puntura vuota ma in una stringa 0 invece.

    
posta Kolyunya 22.05.2013 - 15:18
fonte

6 risposte

8

Una stringa vuota non rappresenta alcun numero intero, quindi al valore nominale la tua domanda ha una risposta banale - non converti una stringa vuota in un numero intero valido.

La domanda alla base della domanda sembra essere "come progettare una robusta utility di conversione da stringa a int non sorprendente". Questo è difficile - prendi in considerazione i seguenti casi aggiuntivi:

  • Quali rappresentazioni del numero di stringhe accetterete? C'è più del decimale - le seguenti stringhe sono anche rappresentazioni dei numeri interi in uso comune: 0x0A, 2x10 ^ 2, 10E5, 08, ...
  • Considererai la conversione di stringhe che rappresentano numeri in virgola mobile in numeri interi?
  • Se rispondi si alla domanda precedente, quale arrotondamento o troncatura useresti?
  • E i numeri razionali?
  • Probabilmente ne troverai ancora qualcuna se ci provassi.

Quindi, in definitiva, la vera risposta alla tua domanda dovrebbe essere quella di utilizzare le funzioni della libreria di conversione da stringa a numero fornite con la lingua e il framework corrente, se ne hanno. Se non ci sono implementazioni per la tua situazione, guarda altre lingue o librerie per l'ispirazione su come gestirle casi nella tua implementazione. Se si documenta cosa fa la funzione di conversione, allora non (o almeno non dovrebbe) sorprendere i client della propria funzione.

    
risposta data 22.05.2013 - 15:41
fonte
2

Se stai convertendo string in int simile alla funzione parseInt di JavaScript, probabilmente vorrai avere '' return NaN o generare un'eccezione, come hai detto.

JavaScript restituisce NaN , ma se la tua lingua non ha quella convenzione o funzione devi lanciare un'eccezione o restituire un valore nullo.

    
risposta data 22.05.2013 - 15:42
fonte
2

Ovviamente dipende da come deve essere utilizzata la funzione.

Queste sono davvero due decisioni di design separate (anche se non indipendenti):

  1. Cosa conta come input non valido?
  2. Che cosa devo fare per l'input non valido?

A proposito di questa prima decisione, qualsiasi "+3", "03", "0x3", "3.0", "3.", "3e0", "3", "3" potrebbe essere dichiarato ragionevolmente in qualche dominio una rappresentazione int valida o non valida. Allo stesso modo, sebbene non rappresentiamo abitualmente il valore zero con una stringa vuota, può essere una scelta perfettamente ragionevole dichiarare che questa funzione considera "" una rappresentazione di zero.

La seconda decisione è più sostanziale. Una funzione ben scritta potrebbe promettere di gestire input non validi con:

  • un modo standard di segnalare un errore (eccezione, ritorno dello stato separato)
  • un modo standard per contrassegnare l'assenza di un valore (ritorno nullo, "opzionale" / "forse" tipo di ritorno, indicatore di presenza-ritorno separato)
  • un "errore" speciale int restituito noto come non valido o altamente improbabile nel dominio di cui la funzione ha a che fare (ad esempio -1 o maxint)
  • un valore predefinito int return (0)
  • un risultato best-effort ben definito (conversione di "123abc" in 123)
  • un valore di ritorno indefinito (ma almeno a valore di ritorno)
  • comportamento completamente indefinito (nessuna promessa - potrebbe corrompere memoria o arresto anomalo)

Lanciare un'eccezione è ovviamente una scelta comune nel mondo moderno, ma a seconda di come verrà utilizzata la funzione, ognuno di questi potrebbe avere senso. Se verrà chiamato un miliardo di volte in un ciclo super stretto su 10k core (si pensi alla scala di Google), a volte la decisione giusta è scrivere altro codice in modo che non passi mai in input non validi.

E due o tre di queste scelte fanno in modo che f ("") restituisca 0, assumendo che "" sia input non valido in primo luogo.

Non credo che una risposta più concreta sarebbe davvero più utile qui, ma nel caso in cui sia tutto ciò che stai cercando: Se sappiamo che stiamo progettando una funzione per uso generale (ad esempio in uno stdlib di una nuova lingua) , una buona regola empirica è trattare gli input non validi nel modo più alto disponibile, in genere l'eccezione. Ma questo dovrebbe essere abbandonato se è chiaramente eccessivo: ad es. se il resto della lib utilizza solo eccezioni per guasti catastrofici, o se catturarli è troppo prolisso o lento rispetto a quanto spesso verrà utilizzata la funzione. (Pensa per un momento perché Java di tutte le lingue evita di lanciare eccezioni su operazioni aritmetiche.)

    
risposta data 22.05.2013 - 21:47
fonte
1

Considerando che 0 è stato inventato per riempire un vuoto nella rappresentazione posizionale dei numeri,

Considerato che la maggior parte delle applicazioni per fogli di calcolo interpretano una cella vuota come valore 0 e che questo comportamento è previsto dagli utenti,

Non è esagerato recuperare una stringa vuota in un numero intero di valori 0 .

La conversione inversa non ha bisogno di essere simmetrica (se non diversamente specificato sul progetto).

    
risposta data 22.05.2013 - 16:26
fonte
1

Perché hai solo bisogno di un metodo string-to-int? Perché non tre:

/** Throws exception if string is unparsable */
int strToInt(String s) throws NumberFormatException

/** Returns null if string is unparsable */
Integer strToIntOrNull(String s)

/** zero if string is unparsable */
int strToIntOrZero(String s)

Ora il client del tuo codice può scegliere e sapere cosa aspettarsi se viene colpito un caso d'angolo.

    
risposta data 22.05.2013 - 17:04
fonte
1

C'è un'altra potenziale risposta qui, e penso che akalenuk lo abbia accennato. Usa una forse monade o qualche altro tipo di opzione simile.

Ad esempio C # /. NET ha Nullable<T> , che non è la stessa ma è carina close , ma limitato a Nullable<int> dovrebbe essere sufficiente.

public static Nullable<int> toInt(string s)
{
    int i = 0;
    if (int.TryParse(s, out I))
        return new Nullable<int>(i);

    return new Nullable<int>();
}

Ricorda inoltre che la trasformazione inInt è non da 1 a 1 e invertibile. Stai trasformando da un set grande, l'insieme di tutte le stringhe possibili, all'insieme di tutti i possibili numeri interi (limitato dai tuoi tipi ... che è rilevante, ma non così tanto). Quindi non è necessario, o addirittura ragionevole supporre che toString sia l'inverso di toInt. Il caso in cui toInt (s) .HasValue == false copre il caso (set di tutte le stringhe) - (set di tutte le stringhe di numeri)

Tuttavia, non abbiamo finito.

Questo è in realtà il caso generale? In questo caso, che dire delle stringhe di numeri per le quali il valore è troppo grande per rientrare in un numero intero? Chiaramente, è ancora un numero. Se non è il caso generale, il tuo caso d'uso vincola l'insieme di valori di output nell'intervallo di un numero intero? Se è così, allora hai finito.

... se no, allora dobbiamo considerare se abbiamo bisogno di un altro tipo (Double? BigInteger?) BigInteger sembra che possa adattarsi al caso generale, ancora limitato dalla memoria (OutOfMemoryException è possibile ).

Alla fine, se stiamo cercando di ottenere qualcosa di più generale possibile, andrei con:

public static Nullable<BigInteger> toInt(string s)
{
    BigInteger bi = new BigInteger();
    if (BigInteger.TryParse(s, out bi))
        return new Nullable<BigInteger>(bi);

    return new Nullable<BigInteger>();
}

Ora, per il grande sesso ... facciamolo in modo funzionale (opzioni F # +):

let toInt s = 
    match BigInteger.TryParse s with
    | (true, parsed) -> Some parsed
    | (false, _) -> None
    
risposta data 22.05.2013 - 18:58
fonte

Leggi altre domande sui tag