Как инициализировать массив с номерами, разделенными определенным интервалом в C # - PullRequest
3 голосов
/ 22 февраля 2012

Я хочу создать массив, содержащий значения от 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, которая позволяет также указать интервал приращения.

Ответы [ 5 ]

17 голосов
/ 22 февраля 2012

Интересным фактом является то, что в каждом опубликованном ответе исправлена ​​ошибка в предложенном вами коде, но только один вызвал, что они это сделали.

Двоичная с плавающей запятойчисла имеют ошибку представления при работе с любой величиной, которая не является долей точной степени двойки.(«3,0 / 4,0» - представимая дробь, потому что нижняя часть имеет степень двойки; «1,0 / 10,0» - нет.)

Поэтому, когда вы говорите:

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

Выфактически не увеличивают «приращение» на 1,0 / 10,0.Вы увеличиваете его на ближайшую представимую дробь, которая имеет точную степень двух в нижней части.Так что на самом деле это эквивалентно:

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. Вы увеличили размер ошибки представления на десять.

Каждый раз, когда вы многократно складываете два числа с плавающей запятой, каждое последующее добавление немного увеличивает общую ошибку представления суммы и это буквально добавляет к потенциально большой ошибке.В некоторых случаях, когда вы суммируете тысячи или миллионы небольших чисел, ошибка может стать намного больше, чем фактическая сумма .

Гораздо лучшим решением будет сделать то, что сделали все остальные. Пересчитать дробь из целых чисел каждый раз .Таким образом, каждый результат получает свою собственную небольшую ошибку представления;он не накапливает ошибки представления ранее вычисленных результатов.

8 голосов
/ 22 февраля 2012

Безобразно, но ...

Enumerable.Range(0,10).Select(i => i/10.0).ToArray();
4 голосов
/ 22 февраля 2012

Нет, нет перечисляемого диапазона, который бы позволял вам это делать, но вы всегда можете разделить на 10:

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

Обратите внимание, что это позволяет избежать ошибки, которая будет накапливаться, если вы повторно суммируете 0.1f. Например, если вы суммируете 10 элементов в myArray в вашем примере кода, вы получите значение, которое ближе к 5.50000048, чем к 5.5.

3 голосов
/ 22 февраля 2012

Вот один из способов:

Enumerable.Range(1,10).Select(i => i /10.0)
2 голосов
/ 22 февраля 2012

Ну, вы можете использовать это:

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

Не уверен, что так лучше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...