我想另一种表达这个问题的方法是使用float
只能在0到1之间的小数位?
我试图通过查看MSDN来解决这个问题。其中精度为7位数。我认为这意味着它只能跟踪0.0000001
的变化。
但是,如果我这样做:
float test = 0.00000000000000000000000000000000000000000001f;
Console.WriteLine(test);
写出9.949219E-44
如果我再添加零,它将输出0
。
我很确定我在这里遗漏了一些东西,因为这种准确度似乎非常错误。主要是浮点数是32位大小,在该精度水平上只有0-1,包含1e + 44个可能的数字......
答案 0 :(得分:30)
标准浮点数的0到1之间有多少个唯一值?
这不是您想要答案的问题,但答案是,不包括0
和1
本身,有2**23 - 1
次正规数和{{1}此范围内的正常数字,总计126 * 2**23
或127 * 2**23 - 1
。
但请注意,这些数字<{>> 均匀分布在1,065,353,215
和0
之间。在1
到1f / 1065353215f
的循环中使用0f
的“delta”对您无效。
如果你想从(十进制)形式0.00 ... 01的步长为0.0到1.0,也许你应该使用 1f
而不是{{1} }。它将代表完全相同的数字。
如果您坚持使用decimal
,请尝试使用float
(比您建议的值大十倍),但请注意,在使用不可表示的数字执行大量添加时,错误可能会累积。< / p>
另请注意:有一些“域名”,您甚至无法依靠float
的前七个有效十进制数字。尝试将值0.000001
或float
保存到0.000986f
变量(确保优化不会将值保存在“更宽”的存储位置)并写出该变量。前七位数字与0.000987f
resp不同。 float
。如果您想使用小数扩展为“短”的数字,您可以再次使用0.0009860000
。
修改:如果您可以为循环使用“二进制”步骤,请尝试使用:
0.0009870000
或等效地作为文字:
decimal
这个增量的好处在于,你通过循环所包含的所有值都可以在float delta = (float)Math.Pow(2, -24);
中完全表示。就在const float delta = 5.96046448e-8f;
之前(下),您将尽可能采取尽可能短的步骤。
答案 1 :(得分:16)
这是7个重要的位数,也就是说,当用指数表示法写入时,你忽略了指数。
0.0000000000000000001234567与12345670000000000000具有相同的有效数字位数,只是用不同的指数表示。这就是允许浮点数存储非常小且非常大的数字的神奇之处。
至于(0,1)中float
究竟有多少可能的数字,我现在不能说完。你有一个23位的尾数,所以2 23 可能的状态。然后有一个8位指数,如果我不是非常错误,它的一半可能值将导致0到1之间的数字。这应该会给你带来大约2 23 + 7 = 2 30 该范围内的可能值。如果有什么可能是上限而不是确切的值。我需要查阅有关精确细节的文档才能确切了解(并且可能重新考虑上面的数学,可能会遗漏几点)。
答案 2 :(得分: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();
}
}
答案 3 :(得分:9)
正浮点值的排序与其编码相同。 0.0f
是0x00000000
。 1.0f
是0x3f800000
。因此,0x3f800000 - 1
个浮点值严格地介于两者之间,或者是1,065,353,215。
如果您想在计数中包含端点,请记住有两种编码为零。
请记住,浮点值的间隔不均匀。 1.0f
与下一个较小数字之间的差异为2**-24
,而0.0f
与下一个较大数字之间的差异为2**-149
。如果要使用统一步骤将浮点数从0增加到1,则可以使用的最小步长为2**-24
。
答案 4 :(得分:0)
由于float类型具有4个字节数据,因此我们可以使用以下代码检查全4个字节(0-255)的所有可能变体,并计算其中有多少个在[0,1]范围内-包括
答案是1065353218
附言取决于个人计算机,代码执行最多可能需要2-3分钟
public static void Main()
{
long count = 0;
//byte checking sub/method
void CheckThisBytes(byte ii, byte jj, byte kk, byte ll)
{
var data = new[] {ii, jj, kk, ll};
var f = BitConverter.ToSingle(data, 0);
//is f in range ?
if (f >= 0.0 && f <= 1.0)
{
count++;
}
}
const int max = 255;
// generate all possible cases
for (var i = 0; i <= max; i++)
{
for (var j = 0; j <= max; j++)
{
for (var k = 0; k <=max; k++)
{
for (var l = 0; l <= max; l++)
{
//check if current float is in range
CheckThisBytes((byte) i, (byte) j, (byte) k, (byte) l);
}
}
}
}
Console.WriteLine("\n Count:" + count);
Console.ReadLine();
//result will be 1065353218
}