SORU
4 EYLÜL 2014, PERŞEMBE


1.0 std geçerli bir çıkış::generate_canonical?

Ben her zaman rasgele sayılar sıfır ile bir arasında yalan olacağını düşündüm1 olmadanyani yarı açık aralığı [0,1) sayılardır. std::generate_canonical documention on cppreference.com bunu doğruluyor.

Aşağıdaki program çalıştırmak, ancak:

#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;
}

Bana şu çıktıyı verir:

Bug!

yani bana MC benim entegrasyonunda sorunlara yol açar 1, mükemmel oluşturur. Bu geçerli bir davranış yoksa benim tarafımda bir hata mı? Bu G 4.7.3 ile aynı çıktıyı verir

g   -std=c  11 test.c && ./a.out

3.3 çınlama

clang   -stdlib=libc   -std=c  11 test.c && ./a.out

Eğer bu doğru bir davranıştır, nasıl 1 kurtulabilir miyim?

1 düzenleyin: Git G aynı sorundan muzdarip gibi görünüyor. Ben

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 ile derleme, ldd çıktı aynı verimi verir

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 düzenleyin: Davranış burada bildirdim: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63176

3 düzenlemek: Çınlama ekibi sorunun farkında gibi görünüyor: http://llvm.org/bugs/show_bug.cgi?id=18767

CEVAP
4 EYLÜL 2014, PERŞEMBE


Sorun eşleme gelen codomain std::mt19937 (std::uint_fast32_t) float; algoritma tarafından açıklanan standart hatalı sonuçlar veriyor (tutarsız ile açıklamasını çıktı algoritma) zaman kaybı hassasiyet oluşursa geçerli İEEE754 yuvarlama modu başka bir şey yuvarlak-negatif-sonsuz (Not Varsayılan yuvarlak-yakın).

Bu 7549723rd çıktı mt19937 ile tohum 4294967257 (0xffffffd9u), hangi zaman yuvarlak 32-bit kayan verir 0x1p 32,, B-max değeri mt19937, 4294967295 (0xffffffffu) o zaman da yuvarlak 32-bit yüzer.

Standart olabilir sağlamak doğru bir davranış olsaydı, bunu belirttiğiniz zaman dönüştürme çıktısı URNG için RealType generate_canonical, yuvarlama. yapılması doğru negatif sonsuzluk; bu verecekti bir doğru sonucu bu durumda. QOİ olarak, libstdc bu değişikliği yapmak için iyi olurdu.

Bu değişiklik olmadan, sadece 1.0 sıra oluşturulur, ancak 0.0 yarım gibi sık sık gerektiği gibi oluşturulur.

std::generate_canonical float doğrudan değil; double sayı üretmek yerine tavsiye ederim ve o zaman eksi sonsuza doğru yuvarlak:

    double rd = std::generate_canonical<double,
        std::numeric_limits<float>::digits>(rng);
    float rf = rd;
    if (rf > rd) {
      rf = std::nextafter(rf, -std::numeric_limits<float>::infinity());
    }

Bu sorun da std::uniform_real_distribution<float>; double dağıtım konusunda uzmanlaşmış float negatif sonsuz doğru sonuç tur için çözüm aynıdır, oluşabilir.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Joanna Okrajni

    Joanna Okraj

    4 EYLÜL 2010
  • L33TNoonProductions

    L33TNoonProd

    24 EYLÜL 2010
  • Liz Morgan

    Liz Morgan

    4 Aralık 2011