web-dev-qa-db-ja.com

srand(time(null))はコンパイラ警告を引き起こします:暗黙の変換は整数精度を失います

この質問にすでに回答されている場合はお詫び申し上げます。

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

using namespace std;

int main () {

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

"暗黙の変換は整数精度を失います: 'time_t'(別名 'long')から 'unsigned int'へ"

上記のコードを実行すると、エラーメッセージが表示されます。 xcode 4.6.1を使用しています。 codepad.orgなどの別のコンパイラを使用すると、乱数のように完全に細かく生成されるので、回避する必要があるのはxcodeの問題だと思いますか?

私はプログラミングを始めたばかりなので、これに関しては完全な初心者です。私のコードに問題がありますか、それとも私のコンパイラですか?

何か助けていただければ幸いです!

20
user2576878

"暗黙の変換は整数精度を失います: 'time_t'(別名 'long')から 'unsigned int'へ"

time()は、ターゲットの_unsigned int_より大きいlongを返すため、暗黙的に精度が失われています。この問題を回避するには、結果を明示的にキャストする必要があります(これにより、「暗黙的な精度の低下」が解消されます)。

_srand( static_cast<unsigned int>(time(NULL)));
_

今が2017年なので、この質問を編集して、_std::chrono::*_で定義されている_<chrono>_によって提供される機能をC++ 11の一部として検討するよう提案します。お気に入りのコンパイラはC++ 11を提供していますか?そうでない場合、それは本当にすべきです!

現在の時刻を取得するには、以下を使用する必要があります。

_#include <chrono>

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

time()が機能するのに、なぜこれを気にする必要があるのですか?

IMO、理由は1つだけで十分です。明確で明示的な型です。十分に大きなチーム間で大規模なプログラムを扱う場合、渡された値が時間間隔を表すのか「絶対」時間を表すのか、そしてどの程度の大きさが重要であるのかを知ることが必要です。 _std::chrono_を使用すると、移植性のあるインターフェースとデータ構造を設計し、タイムアウト、デッドライン、ミリ秒、現在から、または待機時間のブルースをスキップできます。

30
Brian Cain

「nio」で言及されているように、明確な回避策はキャストを明示的にタイプすることです。

より深い説明:

Srand()はパラメーター(srand(unsigned int))としてunsigned intを必要としますが、time()はlong int(long int time())を返し、これはsrand()で受け入れられないため、これを修正するには、コンパイラは単に「long int」を「unsigned int」に型キャスト(変換)する必要があります。

しかし、あなたの場合、コンパイラは代わりにそれについて警告します(コンパイラの設計者はあなたがそれだけであることに注意する必要があると思ったので)。

だからシンプル

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

トリックを行います!

(私が何か間違ったことをした場合は許してください、これはstackoverflowに関する私の最初の答えです)

14
reubenjohn

Srand関数は、引数の型としてunsigned intを持ち、time_tはlong型です。 longの上位4バイトは取り除かれますが、問題はありません。 srandはRandアルゴリズムを4バイト低い時間でランダム化するため、必要以上のデータを提供します。

エラーが発生した場合は、time_t型をunsigned intに明示的にキャストしてみてください。

_srand( (unsigned int) time(NULL) );
_

もう1つの興味深い点は、プログラムを1秒間に2回実行すると同じ乱数が得られることです。これは、望ましくない場合もあります。これは、Randアルゴリズムに同じデータをシードすると、同じ乱数が生成されるためです。シーケンス。または、コードの一部をデバッグし、同じ動作を再度テストする必要がある場合は、望ましい場合があります... srand(123456)のようなものを使用するだけです。

5
nio

これはnotエラーです。コードは有効であり、その意味は明確に定義されています。コンパイラがコンパイルを拒否した場合、コンパイラは言語定義に準拠しません。おそらく、それはwarningであり、コンパイラの作成者が間違いを犯した可能性があると考えていることを示しています。他の人が示唆しているように、警告メッセージの削除を主張する場合は、キャストを追加できます。私は、コンパイラの作者の良いスタイルの概念を満たすために、有効で意味のあるコードを書き換えるのはあまり好きではありません。警告をオフにします。ただし、これを行うと、意図しないデータが変換によって失われる他の場所を見落とす可能性があります。

2
Pete Becker
#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
BlueBit