난 항상 임의의 숫자는 0과 1 사이에 거짓말을 생각 하지 않고1 , 그들은 반 개방 구간 [0,1)에서 숫자 즉. cppreference.com에 documention 의 std::generate_canonical확인한다이.
그러나 다음 프로그램을 실행할 때 :
#include <iostream>
#include <limits>
#include <random>
int main()
{
std::mt19937 rng;
std::seed_seq sequence{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
rng.seed(sequence);
rng.discard(12 * 629143 + 6);
float random = std::generate_canonical<float,
std::numeric_limits<float>::digits>(rng);
if (random == 1.0f)
{
std::cout << "Bug!\n";
}
return 0;
}
다음과 같은 출력을 제공합니다.
Bug!
즉 1, MC 통합에 문제를 일으키는 완벽한을 생성합니다 . 그게 유효한 행동입니까, 아니면 제 편에 오류가 있습니까? 이것은 G ++ 4.7.3과 동일한 출력을 제공합니다.
g++ -std=c++11 test.c && ./a.out
및 clang 3.3
clang++ -stdlib=libc++ -std=c++11 test.c && ./a.out
이것이 올바른 행동이라면 어떻게 피할 수 1있습니까?
편집 1 : git의 G ++는 동일한 문제로 고통받는 것 같습니다. 나는
commit baf369d7a57fb4d0d5897b02549c3517bb8800fd
Date: Mon Sep 1 08:26:51 2014 +0000
로 컴파일 ~/temp/prefix/bin/c++ -std=c++11 -Wl,-rpath,/home/cschwan/temp/prefix/lib64 test.c && ./a.out하면 동일한 출력이 ldd생성됩니다.
linux-vdso.so.1 (0x00007fff39d0d000)
libstdc++.so.6 => /home/cschwan/temp/prefix/lib64/libstdc++.so.6 (0x00007f123d785000)
libm.so.6 => /lib64/libm.so.6 (0x000000317ea00000)
libgcc_s.so.1 => /home/cschwan/temp/prefix/lib64/libgcc_s.so.1 (0x00007f123d54e000)
libc.so.6 => /lib64/libc.so.6 (0x000000317e600000)
/lib64/ld-linux-x86-64.so.2 (0x000000317e200000)
편집 2 : 여기에 동작을보고했습니다. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63176
편집 3 : clang 팀이 문제를 알고있는 것 같습니다 : http://llvm.org/bugs/show_bug.cgi?id=18767
abs(random - 1.f) < numeric_limits<float>::epsilon결과가 1.0에 가까운 지 확인하는 예제 는이 맥락에서 완전히 잘못된 것입니다. 여기에 유효한 결과 인 1.0에 가까운 숫자, 즉 1.0보다 작은 모든 숫자가 있습니다.
1.f == 1.f모든 경우에 (모든 경우가 무엇입니까? 어떤 변수도 보지 못했습니다1.f == 1.f. 여기에는 단 하나의 경우 만 있습니다 :1.f == 1.f, 그것은 변함없이입니다true). 이 신화를 더 퍼 뜨리지 마십시오. 부동 소수점 비교는 항상 정확합니다.