Codice che converte un valore in una rappresentazione diversa, quindi lo converte indietro nel punto in cui è iniziato male, ma come? [chiuso]

34

Stavo leggendo un articolo sulle cattive pratiche di programmazione .

Ha menzionato -

"Yo-Yo code" that converts a value into a different representation, then converts it back to where it started (eg: converting a decimal into a string and then back into a decimal, or padding a string and then trimming it)

Non capisco perché l'esempio particolare che dà è un pessimo modo di scrivere programmi. Mi sembra di tornare indietro se la situazione lo richiede, in modo che il valore possa essere usato.

Qualcuno può spiegare di più su questo?

    
posta user13107 23.10.2014 - 10:39
fonte

6 risposte

124

Anche se do ha bisogno sia della rappresentazione numerica che di una stringa di un numero, è meglio convertire una sola volta e anche aggrapparsi al valore originale, invece di ricominciare ogni volta che ne hai bisogno 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 un'ansia di luce permanente di "Non sono abbastanza intelligente per capire questo sistema complesso", sei sulla strada giusta.

    
risposta data 23.10.2014 - 10:43
fonte
22

È negativo per tre motivi principali:

  1. Mostra che non hai pensato a quale tipo / formato dovrebbe essere la variabile, ma invece la converti in quello che ti serve in quel momento. Questo mostra mancanza di pensiero progettuale.
  2. Probabilmente è uno spreco. Quasi certamente stai sprecando cicli e linee di codice, facendo conversioni che non hanno bisogno di essere lì. Ciò renderà il tuo codice più lento e più gonfio di quanto non sia necessario.
  3. Le conversioni di tipo sono soggette a errori impercettibili. Trascinando queste conversioni attraverso il codice, si aumenta la probabilità di errore.

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

    
risposta data 23.10.2014 - 16:20
fonte
6

Vorrei riformulare la descrizione come "codice che converte un tipo in una diversa rappresentazione allo scopo di fare qualcosa che avrebbe potuto essere eseguito altrettanto bene o meglio nell'originale e poi riconvertirlo Ci sono molte situazioni in cui la conversione di qualcosa in un tipo diverso, che agisce su di esso e la sua conversione è del tutto appropriata e l'errore in tal modo comporterebbe un comportamento scorretto.

Come esempio in cui la conversione è buona:
Uno ha quattro float di valori di segni arbitrari le cui grandezze possono differire di un fattore fino a 1.000, e uno ha bisogno di calcolare la somma entro 0,625 unità nell'ultimo posto. Convertire tutti e quattro i valori in double , calcolando la somma e convertendo il risultato in float sarà molto più efficiente di qualsiasi approccio usando solo float .
I valori in virgola mobile sono a migliore precisione a 0,5 unità nell'ultimo posto (ULP). Questo esempio richiede che l'errore di arrotondamento nel caso peggiore non superi il 25% rispetto all'errore ottimale nel caso peggiore. L'utilizzo di un doppio produrrà un valore che sarà accurato entro 0,5001 ULP. Mentre un requisito ULP 0.625 può sembrare forzato, tali requisiti sono spesso importanti negli algoritmi di approssimazione successiva. Più è strettamente specificato il limite di errore, minore è il requisito di iterazione nel caso peggiore.

Come esempio in cui la conversione è errata:
Uno ha un numero in virgola mobile e desidera produrre una stringa che rappresenterà il suo valore in modo univoco. Un approccio è convertire il numero in una stringa con un certo numero di cifre, provare a riconvertirlo e vedere se il risultato corrisponde.

Ma questo è in realtà un approccio povero. Se una stringa decimale rappresenta un valore che si trova quasi esattamente sul punto a metà tra due valori a virgola mobile, è piuttosto costoso per un metodo stringa-float per garantire che produrrà sempre il valore float più vicino e molti di questi i metodi di conversione non mantengono tale garanzia (tra l'altro, farlo in alcuni casi richiederebbe di leggere tutte le cifre di un numero, anche se erano 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 robusta routine di formattazione decimale da stringa "reversibile" dovrebbe calcolare fino a che punto il valore di uscita è dal valore corretto e continuare ad emettere cifre finché il risultato non è entro 0,375 (ULP) se non a 0,25 (ULP). In caso contrario, potrebbe generare una stringa che alcuni metodi di conversione elaboreranno correttamente, ma altri metodi di conversione no.

A volte è preferibile generare una cifra che potrebbe non essere "necessaria" rispetto all'output di un valore che potrebbe essere interpretato erroneamente. La parte fondamentale è che la decisione sul numero di cifre da produrre dovrebbe essere basata sui calcoli numerici relativi al processo di output, piuttosto che sul risultato del tentativo di un particolare metodo di convertire la stringa in un numero.

    
risposta data 23.10.2014 - 19:59
fonte
2

Vari motivi

  1. È inutile e aggiunge complessità - sia nella quantità di codice da scrivere e mantenere, sia nella quantità di tempo CPU necessaria

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

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

Una buona pratica è solo per mantenere la prima, la rappresentazione più accurata possibile, per tutti i dati che ricevi. Esegui qualsiasi calcolo utilizzando questi dati e convertilo sempre e solo se devi eseguirne l'output o visualizzarlo in un formato più facile da leggere.

    
risposta data 23.10.2014 - 17:35
fonte
0

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

Guarda cosa è successo quando Microsoft ha provato ad implementare un formato "round-trip" specifico per essere sicuro che float < - > le conversioni di stringhe erano sicure: link

    
risposta data 25.10.2014 - 18:38
fonte
0

Quando ero a scuola (e dopo la scuola in ingegneria elettrica) ci è stato insegnato a dividere dopo la moltiplicazione. Divisione spesso molte cifre e arrotondare. Moltiplicare dopo la divisione moltiplica l'errore di divisione.

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

Nella mia lingua, Basic, eseguiamo solo conversioni di tipi (un programma VB6 dedica il 90% del tempo alla 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 valore letterale numerico.

form1.caption = "My Form"

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

Anche questo funziona in base

a = "5"
b = 3

c = a + b (= 8)

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

In ogni caso i miei 3 pet peeves sono

Assegnare stringhe letterali a 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 inline comunque)

Imposta tutti gli oggetti su nulla come le ultime linee prima di una End Function o alla fine del programma.

e un quarto per i programmi brevi

Attenua le tue 3 variabili in un programma a 5 righe in modo poco nitido.

    
risposta data 25.10.2014 - 19:03
fonte

Leggi altre domande sui tag