Il numero intero è usato troppo come un tipo di dati?

9

La maggior parte degli sviluppatori di applicazioni utilizza interi con segno in luoghi in cui si intende realmente utilizzare numeri interi non firmati? Lo faccio sempre, anche i miei collaboratori. Non ho visto molte altre codebase estese (oltre al Delphi VCL) e gli esempi su internet di solito usano l'intero. Mentre gli sviluppatori VCL usano i propri tipi di dati (che sarebbe il modo più pigro per dichiarare le variabili).

Qualcosa sembra un po 'spaventoso per codice come questo

TStuffRec = record
   recordID : Integer;
   thingID : Integer;
   otherThingID : Integer;
end;

quando potrebbe essere scritto come

TStuffRec = record
   recordID : Cardinal;
   thingID : Cardinal;
   otherThingID : Cardinal;
end;

Dal punto di vista funzionale, questi record funzionano quasi sempre allo stesso modo (e si spera che continueranno a funzionare allo stesso modo anche in Delphi a 64 bit). Ma numeri molto grandi avranno problemi di conversione.

Ma ci sono degli svantaggi nell'utilizzare anche gli input non firmati. Principalmente derivante da quanto è fastidioso mescolare i due.

La vera domanda è, è una cosa che viene effettivamente pensata o inclusa nelle migliori pratiche? Di solito è solo lo sviluppatore?

    
posta Peter Turner 25.07.2011 - 22:36
fonte

4 risposte

9

Una ragione per cui non uso i tipi di interi non firmati tanto in Delphi è che possono creare problemi se combinati con interi con segno. Ecco uno che mi ha morso una volta:

for i := 0 to List.Count - 1 do
  //do something here

Ho avuto i dichiarato come numero intero senza segno, (dopo tutto è un indice in una lista che inizia da 0, non deve mai essere negativo, giusto?), ma quando List.Count era 0, sarebbe non cortocircuitare il circuito come previsto perché 0 - 1 valuta un numero molto alto positivo. Oops!

Tra i potenziali problemi di sicurezza insiti nel mescolare interi con segno e senza segno, e i problemi di intervallo, (se hai bisogno di numeri positivi superiori a high(signed whatever) , è molto probabile che finirai per avere bisogno di numeri positivi anche maggiore di high(unsigned whatever) , quindi spostare la dimensione successiva più grande invece di passare da firmato a non firmato della stessa dimensione è solitamente l'azione corretta,) In realtà non ho trovato troppi usi per interi senza segno quando rappresentano la maggior parte dei dati.

    
risposta data 25.07.2011 - 23:57
fonte
3

Per essere onesti, io tendo ad usare gli Integers per abitudine. Mi sono abituato al fatto che offrono intervalli abbastanza grandi per la maggior parte delle situazioni e consentono valori negativi (come -1). In effetti, molte volte usando byte / parola / abbreviazione sarebbe più appropriato. Ora a pensarci posso concentrarmi su questi punti:

  • Prospettiva. Le dimensioni della mappa del mondo sono limitate a 192x192, quindi potrei usare il byte per indirizzare tessere e loop. Ma se la dimensione della mappa deve essere aumentata dovrò passare attraverso ogni uso e sostituirlo con, ad es. parola. Quando devo consentire agli oggetti fuori mappa, dovrei andare di nuovo per passare a smallint.

  • Loops. Spesso scrivo un ciclo "da i: = 0 a Count-1", cosa succede se "i" è un byte e Count = 0 è quel loop che gira da 0 a 255. Non che lo vorrei.

  • Uniforming. È più facile ricordare e applicare "var i: intero;" che fermarsi in ogni caso e pensare "Hm .. qui abbiamo a che fare con l'intervallo 0..120 .. byte .. no, aspetta, potremmo aver bisogno di -1 per non inizializzato .. abbreviazione .. aspetta .. cosa se 128 non è abbastanza .. Arrgh! " o " Perché è piccolo in questo posto, non un cortometraggio? "

  • Combinazione. Quando devo combinare due o più classi insieme, potrebbero utilizzare tipi di dati diversi per i loro scopi, utilizzando tipi più ampi consente di saltare le conversioni non necessarie.

  • -1. Anche quando i valori sono nell'intervallo 0..n-1, spesso ho bisogno di impostare il valore "nessun valore / sconosciuto / non inizializzato / vuoto", che è una pratica comune -1.

L'uso di Integers consente di ignorare tutti questi problemi, dimenticare l'ottimizzazione di basso livello laddove non è necessaria, salire al livello più alto e concentrarsi su problemi più reali.

P.S. Quando uso altri tipi?

  • Contatori, non sono mai negativi e sono di sola lettura al di fuori della loro classe.
  • Ragioni prestazionali / di memoria, forza l'uso di tipi di dati più brevi in determinati luoghi.
risposta data 03.08.2011 - 08:10
fonte
1

La best practice consiste nell'utilizzare un tipo di dati che si adatta alle esigenze dei dati utilizzati (dati previsti).

Esempi di C #: se avessi solo bisogno di supportare da 0 a 255, userei un byte.

Se avessi bisogno di supportare 1.000.000 negativi e positivi, quindi int.

Più grande di 4,2 miliardi, quindi usa un lungo.

Scegliendo il tipo corretto, il programma utilizzerà la quantità ottimale di memoria, così come i diversi tipi usano diverse quantità di memoria.

Ecco un riferimento int C # da MSDN.

int 
 -2,147,483,648 to 2,147,483,647
 Signed 32-bit integer

uint 
 0 to 4,294,967,295
 Unsigned 32-bit integer

long 
 -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
 Signed 64-bit integer

ulong 
 0 to 18,446,744,073,709,551,615
 Unsigned 64-bit integer
    
risposta data 25.07.2011 - 22:55
fonte
1

I tipi interi senza segno dovrebbero essere usati solo per rappresentare i numeri cardinali nelle lingue in cui rappresentano i numeri cardinali. A causa del modo in cui i computer che eseguivano C funzionavano, i tipi di interi senza segno si comportavano come membri di anelli algebrici mod-2 ^ n (cioè i calcoli che overflow si "avvolgevano" in modo prevedibile) e la lingua specifica che in molti casi tali tipi sono tenuti a comportarsi come anelli algebrici astratti anche quando tale comportamento sarebbe incoerente con il comportamento dei numeri cardinali o dei numeri interi matematici.

Se una piattaforma supportava completamente i tipi separati per i numeri cardinali e gli anelli algebrici, suggerirei che i numeri cardinali dovrebbero essere elaborati usando tipi di numero cardinale (e cose che devono essere avvolti usando i tipi di anello). Non solo questi tipi possono memorizzare numeri il doppio delle dimensioni dei tipi firmati, ma un metodo che riceve un parametro di tale tipo non dovrebbe verificare se è stato negativo.

Data la relativa mancanza di tipi di numero cardinale, tuttavia, generalmente è meglio usare semplicemente numeri interi per rappresentare sia numeri interi che numeri cardinali.

    
risposta data 07.05.2014 - 01:40
fonte

Leggi altre domande sui tag