Il codice che converte un valore in una rappresentazione diversa, quindi lo converte nel punto in cui è iniziato è errato, ma come? [chiuso]


35

Stavo leggendo un articolo sulle cattive pratiche di programmazione .

Ha menzionato -

"Codice Yo-Yo" che converte un valore in una rappresentazione diversa, quindi lo converte nel punto in cui è iniziato (ad esempio: conversione di un decimale in una stringa e poi di nuovo in un decimale, oppure riempimento di una stringa e quindi taglio)

Non capisco perché il particolare esempio che fornisce sia un brutto modo di scrivere programmi. Mi sembra giusto riconvertire se la situazione lo richiede in modo che il valore possa essere utilizzato.

Qualcuno può spiegare di più al riguardo?


4
lettura consigliata: discuti di questo $ {blog}
moscerino il

8
Il più delle volte è semplicemente ridondante e succede solo perché il programmatore non conosceva un modo migliore per ottenere ciò che voleva. Il blog dà un esempio tipico pochi paragrafi più avanti: "Roundabout code" that accomplishes in many instructions what could be done with far fewer (eg: rounding a number by converting a decimal into a formatted string, then converting the string back into a decimal). if the situation is so that they have to be used?- quale situazione sarebbe?
Konrad Morawski,

3
@gnat Non capisco come sia una brutta domanda. Se vuoi, posso modificarlo per dire "il codice che converte e ritorna indietro un valore è negativo?" e non si adatta più a quel modello.
Djechlin,

5
Recentemente ho trovato codice in Java che scorre su un array, serializzando ogni oggetto in un oggetto JSON, usando la concatenazione di stringhe, non un serializzatore JSON. Il risultato è stato quindi passato a un metodo privato, che ha analizzato l'array JSON per estrarre un gruppo di ID, quindi ha passato l'ID altrove. Questo era il solo uso di quell'array JSON nel sistema. Questo è il codice yo-yo. Non c'era motivo di trasformazione avanti e indietro. Avremmo potuto semplicemente passare gli ID dagli oggetti originali.
Brandon,

3
decimal myValue = decimal.Parse(dataReader["myColumn"].ToString())è una mia piccola pipì.
Matteo,

Risposte:


125

Anche se tu fa necessità sia la numerica e la rappresentazione di stringa di un numero, è meglio convertire solo una volta e anche appendere al valore originale, invece di convertire di nuovo ogni volta che avete bisogno di uno o l'altro.

Il principio è, come sempre, che il codice che non esiste non può avere difetti sottili , mentre il codice che esiste spesso lo fa. Può sembrare paranoico, ma l'esperienza ci insegna che è appropriato. Se ti avvicini alla programmazione con una leggera ansia permanente di "Non sono abbastanza intelligente da capire questo sistema complesso", sei sulla strada giusta.


5
Ben detto. Noi programmatori dovremmo essere tutti così cauti.
Neil,

58
"il codice che non esiste non può avere difetti impercettibili, mentre il codice che esiste spesso lo fa" vorrei poterti +2 per quello. Non sottovalutare mai il valore di non dover scrivere codice.
Benjamin Gruenbaum,

2
Ma fare un paio di semplici operazioni (converti in stringa e ritorno) potrebbe essere molto meno complesso (più facile da capire e codificare) rispetto al modo "giusto" di manipolare i bit. E mantenere tutti i dati di una categoria in una singola forma è spesso una buona idea, anche se determinati dati saranno inevitabilmente convertiti in altre forme.
Daniel R Hicks,

36
@DanielRHicks quindi convertiamo quella semplice data (10 novembre 2014) in una stringa, -> 10-11-2014 e torniamo a una data -> (11 ottobre 2014) hey aspetta cosa?
Pieter B,

20
@PieterB Esiste un grande software di contabilità tedesco che non funziona su computer con impostazioni locali non tedesche perché lo fa. Prima converte la data in stringa utilizzando le impostazioni internazionali del sistema, quindi tenta di analizzarle con impostazioni internazionali fisse e si lamenta del formato illegale. Fa lo stesso con numeri e separatori decimali variabili, tranne per il fatto che non si lamenta, corrompe i dati e mostra comportamenti strani. Mi ci sono voluti giorni per capirlo.
CodesInChaos,

23

È negativo per tre motivi principali:

  1. Mostra che non hai pensato a quale tipo / formato dovrebbe effettivamente essere la variabile, ma la stanno invece convertendo in ciò di cui hai bisogno in quel momento. Ciò dimostra la mancanza di pensiero progettuale.
  2. È probabilmente uno spreco. Stai quasi sicuramente sprecando cicli e righe di codice, facendo conversioni che non hanno bisogno di essere lì. Questo renderà il tuo codice più lento e più gonfio di quanto debba essere.
  3. Le conversioni di tipo sono soggette a errori sottili. Punteggiando queste conversioni attraverso il codice si aumenta la probabilità di errore.

Sospetto che la ragione 1 sia la ragione a cui la tua fonte stava pensando in base al contesto in cui è stata menzionata.


6

Vorrei riformulare la descrizione come "codice che converte un tipo in una rappresentazione diversa allo scopo di fare qualcosa che avrebbe potuto essere fatto altrettanto bene o meglio nell'originale e poi lo converte indietro. Ci sono molte situazioni in cui convertire qualcosa in un tipo diverso, agire su di esso e riconvertirlo è del tutto appropriato e la mancata osservanza comporterebbe un comportamento errato.

Come esempio in cui la conversione è buona:
uno ha quattro floatvalori di segni arbitrari le cui magnitudini possono differire di un fattore fino a 1.000 e si deve calcolare la somma entro 0,625 unità nell'ultimo posto. Convertire tutti e quattro i valori in double, calcolare la somma e riconvertire il risultato floatsarà molto più efficiente di qualsiasi approcciofloat da solo.
I valori in virgola mobile sono nella migliore delle ipotesi accurati a 0,5 unità nell'ultimo posto (ULP). Questo esempio richiederebbe che l'errore di arrotondamento nel caso peggiore non superi di oltre il 25% l'errore ottimale nel caso peggiore. L'uso di un doppio produrrà un valore che sarà accurato entro 0,5001 ULP. Sebbene un requisito ULP di 0,625 possa sembrare forzato, tali requisiti sono spesso importanti negli algoritmi di approssimazione successiva. Più strettamente viene specificato il limite di errore, minore è il requisito di iterazione nel caso peggiore.

Ad esempio, dove la conversione è errata:
uno ha un numero in virgola mobile e desidera generare una stringa che rappresenterà il suo valore in modo univoco. Un approccio consiste nel convertire il numero in una stringa con un determinato numero di cifre, provare a riconvertirlo e vedere se il risultato corrisponde.

Ma questo è in realtà un approccio scadente. Se una stringa decimale rappresenta un valore che si trova quasi esattamente sul punto a metà strada tra due valori in virgola mobile, è abbastanza costoso per un metodo stringa-float garantire che produrrà sempre il più vicinofloat valore e molti di questi metodi di conversione don mantenere una tale garanzia (tra l'altro, farlo in alcuni casi richiederebbe la lettura di tutte le cifre di un numero, anche se era lungo miliardi di cifre).

È molto più economico per un metodo garantire che restituirà sempre un valore compreso tra 0,5625 unità nell'ultimo posto (ULP) del valore rappresentato. Una solida routine di formattazione da decimale a stringa "reversibile" dovrebbe calcolare la distanza tra il valore di output e il valore corretto e continuare a immettere cifre fino a quando il risultato non è compreso tra 0,375 (ULP) se non 0,25 (ULP). Altrimenti, potrebbe generare una stringa che alcuni metodi di conversione elaboreranno correttamente, ma altri metodi di conversione no.

A volte è meglio emettere una cifra che potrebbe non essere "necessaria" piuttosto che emettere un valore che potrebbe essere male interpretato. La parte fondamentale è che la decisione su quante cifre devono essere emesse dovrebbe essere presa sulla base di calcoli numerici relativi al processo di output, piuttosto che sul risultato del tentativo di un particolare metodo di riconvertire la stringa in un numero.


1
Il tuo esempio non restituisce il valore originale che è ciò di cui l'OP chiede. Restituisce semplicemente un valore con lo stesso tipo, calcolato da più input.
CJ Dennis,

2

Ragioni varie

  1. È inutile e aggiunge complessità: sia la quantità di codice da scrivere e gestire, sia la quantità di tempo della CPU necessaria

    1. Può perdere precisione o peggio, corrompere del tutto il valore

    2. Spreca memoria (potenzialmente, a seconda della lingua) man mano che si finisce per memorizzare più rappresentazioni di un numero necessario

Una buona pratica è solo quella di mantenere la prima rappresentazione più accurata possibile per tutti i dati che ricevi. Esegui i calcoli utilizzando questi dati e convertili sempre e solo se hai bisogno di emetterli o visualizzarli in un formato più facile da leggere.


ciò non sembra aggiungere nulla di sostanziale rispetto ai punti formulati e spiegati nelle risposte precedenti
moscerino del

2
Ciò giustifica un voto contrario? Credo che il mio post sia potenzialmente più conciso
Jon Story,

le risposte precedenti mi sembrano davvero più concise, entrambe
moscerino il

0

Perché? Perché anche il migliore di noi può commettere errori.

Guarda cosa è successo quando Microsoft ha cercato di implementare un formato "round-trip" specificamente per assicurarsi che le conversioni di stringhe float <-> fossero sicure: https://stackoverflow.com/q/24299692/541686


0

Quando ero a scuola (e dopo la scuola di ingegneria elettrica) ci hanno insegnato a dividere dopo la moltiplicazione. Divide spesso molte cifre e viene arrotondato. Moltiplicare dopo la divisione moltiplica l'errore di divisione.

Le conversioni di tipo sono le stesse, rischi di perdere dati. CInt (1.3) = 1.

Nella mia lingua, di base, eseguiamo solo conversioni di tipo (un programma VB6 impiega il 90% del tempo a eseguire la conversione ANSI / Unicode, per tutte le chiamate API eseguite dal runtime).

La conversione del tipo è implicita in tutto ciò che facciamo.

 Print 5

La stringa "5" viene stampata dal letterale numerico.

form1.caption = "My Form"

La stringa unicode letterale viene convertita in una stringa ANSI e inviata a SetWindowsTextA dal pacchetto dei moduli.

Anche questo funziona in base

a = "5"
b = 3

c = a + b (= 8)

Sono un programmatore di varianti in questi giorni - non penso nemmeno al tipo. Mi baso solo sulle autoconversioni.

Comunque sono i miei 3 animali domestici

Assegnare valori letterali stringa alle variabili per usarle (spreca memoria e rallenta)

Funzioni inutili quando il codice potrebbe essere in linea (e il compilatore probabilmente annullerà la tua funzione e la incorporerà comunque)

Impostare tutti gli oggetti su niente come ultime righe prima di una funzione finale o fine del programma.

e un quarto per i programmi brevi

Dimmerare inutilmente le 3 variabili in un programma a 5 righe.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.