如何在C#中使用以特定间隔分隔的数字初始化数组
我想创建一个包含从0到1的值的数组,间隔为0.1。 我可以用:
float[] myArray = new float[10]; float increment = 0.1; for(i = 0; i < 10; i++) { myArray[i] = increment; increment += 0.1; }
我想知道是否有像Enumerable.Range
这样的函数允许指定增量间隔。
一个有趣的事实是,到目前为止发布的每个答案都修复了您提议的代码中的错误 ,但只有一个人已经说过他们已经这样做了。
当处理任何不是精确2的幂的一小部分的数量时,二进制浮点数具有表示错误 。 (“3.0 / 4.0”是可表示的分数,因为底部是2的幂;“1.0 / 10.0”不是。)
因此,当你说:
for(i = 0; i < 10; i++) { myArray[i] = increment; increment += 0.1; }
实际上你并没有将“增量”增加1.0 / 10.0。 您将通过底部具有精确幂2的最接近的可表示分数递增它。 所以实际上这相当于:
for(i = 0; i < 10; i++) { myArray[i] = increment; increment += (exactly_one_tenth + small_representation_error); }
那么, 第十个增量的价值是多少? 显然它是10 * (exactly_one_tenth + small_representation_error)
,它显然等于exactly_one + 10 * small_representation_error
。 您已将表示错误的大小乘以10。
每次重复将两个浮点数加在一起时, 每次后续添加都会略微增加总和的总表示误差,并且实际上会增加一个潜在的大错误。 在某些情况下,您要汇总数千或数百万个小数字,误差可能会远远大于实际总数 。
更好的解决方案是做其他人所做的事情。 每次从整数重新计算分数 。 这样每个结果都有自己的小表示错误; 它不会累积先前计算结果的表示错误。
丑,但……
Enumerable.Range(0,10).Select(i => i/10.0).ToArray();
不,没有可以允许你这样做的可数范围,但你可以总是除以10:
foreach (int i in Enumerable.Range(0, 10)) array[i] = (i + 1) / 10.0f
请注意,这可以避免在重复求和0.1f时累积的错误。 例如,如果在示例代码中对myArray
中的10个元素求和,则得到的值比5.5更接近5.50000048。
这是一种方式:
Enumerable.Range(1,10).Select(i => i /10.0)
那你可以用这个:
Enumerable.Range(1,10).Select(x => x / 10.0).ToArray()
不确定这是否更好。