Почему у double и float ошибка накапливается не равномерно?
Может кто объяснить, почему ошибка накапливается не равномерно, а довольно странными скачками?
Сейчас я экспериментирую с накапливанием ошибки для float и double.
Я провожу вычисления по следующей формуле:
.
Вычисления проводятся циклично в течении определённого промежутка времени. Результат вывожу в текстовые два текстовых файла (один для float, другой для double). Код написан на C++, он приведен ниже. Компилирую без оптимизации!
#include <iostream>
#include <fstream>
#include <ctime>
using namespace std;
int main() {
float y = 1.0;
double yd = 1.0;
int k = 1;
int end = 0;
ofstream fout_float("output_float.txt");
ofstream fout_double("output_double.txt");
if (!fout_float.is_open() || !fout_double.is_open())
return -1;
fout_float.precision(64);
fout_double.precision(64);
while (end / CLOCKS_PER_SEC / 60 != 10) {
float tmp_y = y;
double tmp_yd = yd;
if (k < INT_MAX / 10000) {
y = (y / k) * k;
yd = (yd / k) * k;
k++;
} else {
k = 1;
}
end = clock();
if (end % (CLOCKS_PER_SEC * 20) == 0) {
cout << end / CLOCKS_PER_SEC << "s\n";
fout_float << end / CLOCKS_PER_SEC / 60 << '\t' << 1 - y << '\t' << tmp_y - y << endl;
fout_double << end / CLOCKS_PER_SEC / 60 << '\t' << 1 - yd << '\t' << tmp_yd - yd << endl;
}
}
fout_float.close();
fout_double.close();
return 0;
}
Все бы хорошо, но я не особо понимаю, почему я получаю следующие результаты.
У float.
Как и ожидалось, ошибка есть, но почему она делает это странными скачками, я понять не могу.
Зачастую ошибка равна 0, иногда же она 5.9604644775390625e-08 или -5.9604644775390625e-08.
У double
Как и полагается, ошибка намного меньше. Но она продолжает так же скакать.
Ошибка бывает равна как 0, так и +-1.1102230246251565404236316680908203125e-16
Ответы (2 шт):
Это всё деление.Его результат не получается вписать в эту переменную.Вот и всё.
| float | 0 | . | 00000000 |
|---|---|---|---|
| результат деления | 0 | . | 09382892876 |
876 не получается вместить, и они удаляются.Вот и неточность деления.
Попробуем посчитать до 1000 с шагом 10 добавляя погрешность от -.5 до +.5 на каждом шаге:
var noacc = 0, acc = 0
for (var q=1; q<=100; ++q) {
var err = Math.random() - .5
noacc = q*10 + err
acc += 10 + err
console.log(noacc.toFixed(3), acc.toFixed(3))
}
// Просто прокрутить вывод до низа
setTimeout(() => document.querySelector(".as-console-wrapper").scrollTop = 1e6)
.as-console-wrapper.as-console-wrapper { max-height: 100vh }

