How to initialize an array with numbers separated by a specific interval in C#

回眸只為那壹抹淺笑 提交于 2019-12-10 18:34:50

问题


I want to create an array containing values from 0 to 1 with interval of 0.1. I can use:

float[] myArray = new float[10];
float increment = 0.1;
for(i = 0; i < 10; i++)
{
   myArray[i] = increment;
   increment += 0.1;
}

I was wondering whether there is a function like Enumerable.Range that permits to specify also the increment interval.


回答1:


An interesting fact is that every answer posted so far has fixed the bug in your proposed code, but only one has called out that they've done so.

Binary floating point numbers have representation error when dealing with any quantity that is not a fraction of an exact power of two. ("3.0/4.0" is a representable fraction because the bottom is a power of two; "1.0/10.0" is not.)

Therefore, when you say:

for(i = 0; i < 10; i++) 
{
    myArray[i] = increment;    
    increment += 0.1; 
} 

You are not actually incrementing "increment" by 1.0/10.0. You are incrementing it by the closest representable fraction that has an exact power of two on the bottom. So in fact this is equivalent to:

for(i = 0; i < 10; i++) 
{
    myArray[i] = increment;    
    increment += (exactly_one_tenth + small_representation_error);
} 

So, what is the value of the tenth increment? Clearly it is 10 * (exactly_one_tenth + small_representation_error) which is obviously equal to exactly_one + 10 * small_representation_error. You have multiplied the size of the representation error by ten.

Any time you repeatedly add together two floating point numbers, each subsequent addition increases the total representation error of the sum slightly and that adds up, literally, to a potentially large error. In some cases where you are summing thousands or millions of small numbers the error can become far larger than the actual total.

The far better solution is to do what everyone else has done. Recompute the fraction from integers every time. That way each result gets its own small representation error; it does not accumulate the representation errors of previously computed results.




回答2:


Ugly, but...

Enumerable.Range(0,10).Select(i => i/10.0).ToArray();



回答3:


No, there's no enumerable range that allows you to do that, but you could always divide by 10:

foreach (int i in Enumerable.Range(0, 10))
    array[i] = (i + 1) / 10.0f

Note that this avoids the error that will accumulate if you repeatedly sum 0.1f. For example, if you sum the 10 elements in the myArray in your sample code, you get a value that's closer to 5.50000048 than 5.5.




回答4:


Here is one way:

Enumerable.Range(1,10).Select(i => i /10.0)



回答5:


Well you could use this:

Enumerable.Range(1,10).Select(x => x / 10.0).ToArray()

Not sure if that's better though.



来源:https://stackoverflow.com/questions/9398851/how-to-initialize-an-array-with-numbers-separated-by-a-specific-interval-in-c-sh

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!