标准浮点数的0到1之间有多少个唯一值?

Mat*_*ern 29 c# floating-point ieee-754

我想另一种表达这个问题的方法是你可以使用float只有0到1之间的小数位数吗?

我试着通过查看MSDN来解决这个问题.其中精度为7位数.我认为这意味着它只能追踪变化0.0000001.

但是,如果我这样做:

float test = 0.00000000000000000000000000000000000000000001f;
Console.WriteLine(test);
Run Code Online (Sandbox Code Playgroud)

它写出来了 9.949219E-44

如果我再添加零,它将输出0.

我很确定我在这里遗漏了一些东西,因为这种准确度似乎非常错误.主要是浮动的大小为32位,在该精度级别仅为0-1,包含1e + 44个可能的数字......

Jep*_*sen 30

标准浮点数的0到1之间有多少个唯一值?

这不是你想要答案的问题,但答案是,不包括01他们自己,在这个范围内存在2**23 - 1次正规数和126 * 2**23正常数,总数为127 * 2**23 - 1,或1,065,353,215.

但需要注意的是,这些数字是不是均匀分布之间的间隔01.使用的"增量" 1f / 1065353215f从一个循环0f1f会不会为你工作.

如果你想从0.0到1.0步长(十进制)形式0.00 ... 01的步长,也许你应该使用decimal而不是float.它将完全代表这样的数字.

如果您坚持使用float,请尝试0.000001(比您建议的值大10倍),但请注意,在使用不可表示的数字执行很多添加时,错误可能会累积.

另请注意:有一些"域",您甚至不能指望a的前七个有效十进制数字float.尝试例如保存价值0.000986f或者0.000987ffloat变量(可以肯定的优化没有在一个"更广泛的"存储位置保存值),并写出该变量.前七位数字与0.0009860000resp不同.0.0009870000.decimal如果您想使用十进制扩展为"短"的数字,您可以再次使用.

编辑:如果您可以为循环使用"二进制"步骤,请尝试:

float delta = (float)Math.Pow(2, -24);
Run Code Online (Sandbox Code Playgroud)

或等效地作为文字:

const float delta = 5.96046448e-8f;
Run Code Online (Sandbox Code Playgroud)

关于这个delta的好处是,你通过循环包含的所有值都可以在你的中完全表示float.就在(下)之前1f,您将尽可能采取尽可能短的步骤.

  • 如果你在循环中计算'0.000001*i`,而不是求和,你将只有一个舍入错误来处理,而不是累积. (9认同)

Joe*_*oey 17

它是7 位有效数字,也就是说,当以指数表示法写入时,您忽略指数.

0.0000000000000000001234567与12345670000000000000具有相同的有效数字位数,只是用不同的指数表示.这是允许浮点数存储非常小且非常大的数字的神奇之处.

至于究竟有多少可能的数字float(0,1),我现在不能说完全正确.你有一个23位的尾数,所以有2 23种可能的状态.然后有一个8位指数,如果我没有非常错误,它的一半可能值将导致0到1之间的数字.这应该会给你留下大约2 23 + 7 = 2 30个可能的值在该范围内.如果有什么可能是上限而不是确切的值.我需要查阅有关精确细节的文档才能确切知道(并且可能重新考虑上面的数学可能会遗漏几点).

  • 如果算数正确,则正次正规数的数量为"2**23 - 1",而严格低于1的正正数的数量为"126*2**23".从0到1的开放区间中的总数是"127*2**23 - 1"或"1,065,353,215". (4认同)

Mag*_*ken 13

我写了这个非常愚蠢的程序,它给出了答案1065353217,实际上只是2 30(1073741824).如果您要查找不包括 0和1的所有数字,则从该数字中减去2. 顺便说一下,最小的非零数字似乎是1.401298E-45.

class Program
{
    public unsafe static int Search()
    {
        int i = 0;
        float* f = (float*)&i;
        while (*f >= 0 && *f <= 1)
        {
            f = (float*)&i;
            i++;
        }

        return i;
    }

    static void Main(string[] args)
    {
        Console.WriteLine(Search());
        Console.ReadLine();
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @MatthewMcGovern - 相邻浮点数之间的步长随其比例而变化,因此没有一个浮点值可以逐步点击它们.你究竟想做什么? (2认同)

Ste*_*non 9

正浮点值的排序与其编码相同. 0.0f0x00000000. 1.0f0x3f800000.因此,0x3f800000 - 1浮点值严格介于两者之间,即1,065,353,215.

如果要在计数中包含端点,请记住有两种编码为零.

还要记住,浮点值不是均匀间隔的.之间的差1.0f和所述下一个更小的数是2**-24,而之间的差0.0f和下一个较大数为2**-149.如果要使用统一步长将浮点数从0增加到1,则可以使用的最小步长是2**-24.