Ваши добавления - это, в основном, случайное блуждание, а ошибка, которую вы делаете, - это другое случайное блуждание (потому что у вас есть ошибка округления почти на каждом шаге). (Обратите внимание, что Eigen::MatrixXf::Random
заполняет матрицу случайными значениями в [-1, 1]
.)
Предположим, что в среднем вы используете значение с плавающей запятой 10.0
(оценивается только по той единственной точке данных, которую вы указали). Ваш эпсилон (сколько абсолютной ошибки округления вы, вероятно, допустите при любом добавлении), таким образом, составляет около 10.0 * 6e-8
(число с плавающей запятой 2 -23 или около 6e-8 ) или около 6e-7
.
Если вы выполните N = 1000000
случайные шаги накопления ошибок с размером шага +6e-7
(или -6e-7
), у вас будет хороший шанс оказаться на отметке sqrt(N) * stepSize = 1000 * 6e-7 = 6e-4
(см. здесь ) что не слишком совпадает с вашим 0,01%.
Я бы также оценил абсолютную ошибку в 1000 * 10 * 1e-16 = 1e-12
для сложения 1 миллиона случайных двойных чисел от -1 до 1 из-за точности с плавающей запятой.
Это явно не строгая математическая обработка. Это просто показывает, что ошибка, безусловно, в правильном поле.
Распространенным способом решения этой проблемы является сортировка чисел с плавающей точкой в порядке возрастания величины перед их добавлением, но при этом вы все равно можете быть произвольно неточными. (Пример: продолжайте добавлять число 1.0f
к себе - сумма перестанет увеличиваться на 2^24
, где эпсилон станет больше 1.0f
.)