2013-07-12 8 views
16

Ci scusiamo se questa domanda ha già avuto risposta.srand (time (null)) avverte il compilatore: la conversione implicita perde la precisione di un numero intero

#include <iostream> 
#include <cstdlib> 
#include <ctime> 

using namespace std; 

int main() { 

srand(time(NULL)); 
cout << rand(); 
} 

"conversione implicita perde precisione intero: 'time_t' (aka 'lunga') per 'unsigned int'"

È il messaggio di errore Im ottenendo quando eseguo il codice di cui sopra. Sto usando xcode 4.6.1. Ora quando uso un altro compilatore come quello di codepad.org, esso esegue perfettamente bene ciò che sembra come numeri casuali, quindi presumo che sia un problema di xcode che devo risolvere?

Ho appena iniziato la programmazione quindi sono un principiante assoluto quando si tratta di questo. C'è un problema con il mio codice o è il mio compilatore?

Qualsiasi aiuto sarebbe apprezzato!

+1

la sua non è raro che anela ad avere più precisione rispetto unsigneds. – PlasmaHH

risposta

25

"conversione implicita perde precisione intero: 'time_t' (aka 'lunga ') per 'unsigned int'"

stai perdendo precisione implicitamente perché time() restituisce una long che è più grande di un unsigned int sul vostro obiettivo. Per risolvere questo problema, è necessario lanciare esplicitamente il risultato (eliminando in tal modo la "perdita implicita di precisione"):

srand(static_cast<unsigned int>(time(NULL))); 

Dato che è ora il 2017, sto modificando questa domanda a suggerire che si considerare le funzionalità fornite da std::chrono::* definite in <chrono> come parte di C++ 11. Il tuo compilatore preferito fornisce C++ 11? In caso contrario, dovrebbe davvero!

Per ottenere l'ora corrente, si consiglia di utilizzare:

#include <chrono> 

void f() { 
    const std::chrono::time_point current_time = std::chrono::system_clock::now(); 
} 

Perché dovrei perdere tempo con questo quando time() opere?

IMO, una sola ragione è sufficiente: tipi chiari, espliciti. Quando si affrontano programmi di grandi dimensioni tra team abbastanza grandi, sapere se i valori trasmessi rappresentano intervalli di tempo o tempi "assoluti" e quali sono le grandezze critiche.Con std::chrono è possibile progettare interfacce e strutture dati che sono portatili e saltare sul blues is-that-time-out-a-dead-mill-sec-time-or-wait-was-is-secondi.

+5

Poiché questa domanda è codificata in C++: _Please_ non utilizzare i cast in stile C. 'srand (static_cast (time (NULL));' funziona egregiamente e rende il tuo codice tutto molto bello e brillante. Come bonus, evita tonnellate di potenziali bug che possono insinuarsi con i cast in stile C. .. – ComicSansMS

+1

In effetti, ho incautamente pensato che fosse una domanda in C senza guardare i tag. La risposta è stata modificata per correggere il problema –

+1

Probabilmente ha usato un target diverso, uno per il quale non vi era alcuna perdita di precisione tra "long" e 'unsigned int' (l'altro compilatore era per una macchina a 32 bit e questo è 64-bit, forse?) –

4

La funzione srand ha unsigned uns come tipo di argomento, time_t è di tipo long. i 4 byte superiori da lunghi vengono eliminati, ma non ci sono problemi. srand randomizzerà l'algoritmo rand con 4 byte inferiori di tempo, quindi fornirai più dati del necessario.

se si ottiene un errore, provare a lanciare solo in modo esplicito il tipo time_t a unsigned int:

srand((unsigned int) time(NULL)); 

Un'altra cosa interessante è che se si esegue il programma due volte nello stesso secondo, si otterrà la stesso numero casuale, che a volte può essere indesiderato, perché se si semina l'algoritmo di Rand con gli stessi dati, genererà la stessa sequenza casuale. Oppure può essere desiderabile durante il debug di un certo pezzo di codice e la necessità di testare ancora una volta lo stesso comportamento ... allora è sufficiente utilizzare qualcosa come srand(123456)

2

Questo è non un errore. Il codice è valido e il suo significato è ben definito; se un compilatore rifiuta di compilarlo, il compilatore non è conforme alla definizione della lingua. Più probabilmente, è un avviso , e ti sta dicendo che lo scrittore del compilatore pensa che potresti aver fatto un errore. Se insisti a eliminare i messaggi di avviso, potresti aggiungere un cast, come altri hanno suggerito. Non sono un grande fan della riscrittura di un codice valido e significativo per soddisfare la nozione di buon stile del produttore di compilatori; Spegnerei l'avviso. Se lo fai, però, potresti trascurare altri luoghi in cui una conversione perde i dati che non hai inteso.

+0

Solo perché qualcosa è tecnicamente corretto non significa che sia una buona idea. Sappiamo che c'è una possibilità di troncamento: in questo caso preferirei che spegni un avvertimento del compilatore che potrebbe salvare la bacon quando sei più distratto –

+0

@MarkRansom - vuoi rimuovere il cast su una piattaforma in cui 'time_t' e 'non firmato 'hanno le stesse dimensioni, dal momento che il motivo del cast non si applica più? Forse condizionarlo, in base alla piattaforma? Inseguire gli avvertimenti può essere una fossa senza fondo. –

+0

Non avrei certamente condizionato un cast del genere, e non lo rimuoverei se avessi bisogno di supportare più piattaforme. Ora posso vederlo, ma in futuro qualcuno verrà a StackOverflow e chiederà "Perché questo cast qui quando non fa niente?" –

13

Come menzionato da "nio", una soluzione pulita sarebbe quella di digitare espressamente il cast. spiegazione

Deeper:

Lo srand() richiede un unsigned int come parametro (srand(unsigned int)), ma il tempo() restituisce un long int (long int time()) e questo non è accettata dal srand() in modo al fine per risolvere questo problema, il compilatore deve semplicemente typecast (convert) "long int" in "unsigned int".

MA nel tuo caso il compilatore ti avverte invece (come i progettisti del compilatore pensavano dovresti essere a conoscenza che è tutto).

Quindi, un semplice

srand((unsigned int) time(NULL));

farà il trucco!

(mi perdoni se ho fatto qualcosa di sbagliato, questa è la mia prima risposta su StackOverflow)

+1

Ottima prima risposta! –

0
#include <stdlib.h> 
#include <iostream>   //rand 
#include <time.h>  //time 

float randomizer(int VarMin, int VarMax){ 
    srand((unsigned)time(NULL)); 
     int range = (VarMax - VarMin); 
     float rnd = VarMin + float(range*(rand()/(RAND_MAX + 1.0))); 
return rnd; 
} 
+0

Come posso personalizzare questa funzione per generare un numero casuale in microsecondi? Con "srand ((unsigned) time (NULL))", non è possibile! Qual'è la soluzione? – BlueBit

+0

È possibile utilizzare una funzione specifica della piattaforma come 'gettimeofday' o' GetSystemTimeAsFileTime' per restituire l'ora con precisione al secondo inferiore. – dan04

Problemi correlati