代码之家  ›  专栏  ›  技术社区  ›  Not Sure

截断时的浮点舍入

  •  3
  • Not Sure  · 技术社区  · 17 年前

    对于x86 FPU专家来说,这可能是一个问题:

    我正在尝试编写一个函数,生成[min,max]范围内的随机浮点值。问题是,我的生成器算法(如果你好奇的话,可以使用浮点Mersenne Twister)只返回[1,2]范围内的值——也就是说,我想要一个包含的上界,但我的“源”生成的值来自一个排他上界。这里的问题是,底层生成器返回一个8字节的双精度浮点值,但我只需要一个4字节的浮点值,并且我使用默认的FPU舍入模式Nearest。

    我想知道的是,在这种情况下,当FPU内部80位值足够接近时,截断本身是否会导致返回值包含max,或者我是否应该在max值乘以中间随机数之前增加max值的有效位[1,2],或者我是否应该改变FPU模式。当然,还有其他想法。

    以下是我当前使用的代码,我确实验证了1.0f解析为0x3f800000:

    float MersenneFloat( float min, float max )
    {
        //genrand returns a double in [1,2)
        const float random = (float)genrand_close1_open2(); 
        //return in desired range
        return min + ( random - 1.0f ) * (max - min);
    }
    

    编辑: 答案是肯定的,在这种情况下,从double到float的截断足以导致结果包含max。有关更多信息,请参阅Crashworks的答案。

    3 回复  |  直到 17 年前
        1
  •  4
  •   Crashworks    17 年前

    SSE ops将微妙地改变该算法的行为,因为它们没有中间的80位表示——数学实际上是在32位或64位中完成的。好消息是,您可以通过简单地将/ARCH:SSE2命令行选项指定给MSVC,轻松地测试它并查看它是否会改变结果,这将导致它使用SSE标量运算,而不是x87 FPU指令进行普通浮点运算。

    我不确定整数边界周围的精确舍入行为是什么,但您可以测试看看当1.999..时会发生什么。。从64位四舍五入到32位

    static uint64 OnePointNineRepeating = 0x3FF FFFFF FFFF FFFF // exponent 0 (biased to 1023), all 1 bits in mantissa
    double asDouble = *(double *)(&OnePointNineRepeating);
    float asFloat = asDouble;
    return asFloat;
    

    编辑,结果: 原始海报运行了此测试,发现通过截断,1.99999在有/无/arch:SSE2的情况下将取整为2。

        2
  •  0
  •   Pete Kirkham    17 年前

    如果调整舍入,使其包含范围的两端,那么这些极值的可能性是否仅为任何非极值的一半?

        3
  •  0
  •   rlbond    17 年前

    使用截断,永远不会包含最大值。

    你确定你真的需要max吗?从字面上看,你几乎没有机会准确地降落在最大点上。

    float MersenneFloat( float min, float max )
    {
        double random = 100000.0; // just a dummy value
        while ((float)random > 65535.0)
        {
            //genrand returns a double in [1,2)
            double random = genrand_close1_open2() - 1.0; // now it's [0,1)
            random *= 65536.0; // now it's [0,65536). We try again if it's > 65535.0
        }
        //return in desired range
        return min + float(random/65535.0) * (max - min);
    }
    

    编辑:改进的算法

    推荐文章