Сумма, превышающая допустимое значение в циклических числах

Я недавно создал эту простую программу, чтобы найти среднюю скорость.

Средняя скорость = Δx / Δt

Я выбрал х как функцию т как х = t^2

Следовательно v = 2t

также, avg v = (x2 - x1) / (t2 - t1)

Я выбрал интервал, чтобы быть т = 1s to 4s. Подразумевает х идет от 1 to 16

Следовательно avg v = (16 - 1) / (4 - 1) = 5

Теперь программа:

#include <iostream>

using namespace std;
int main() {
float t = 1, v = 0, sum = 0, n = 0;  // t = time, v = velocity, sum = Sigma v, n = Sigma 1
float avgv = 0;

while( t <= 4 ) {
v = 2*t;
sum += v;
t += 0.0001;
n++;
}
avgv = sum/n;
cout << "\n---->  " << avgv << "  <----\n";
return 0;
}

Я использовал очень маленькие приращения время рассчитать скорость во многих моментах. Теперь, если приращение T составляет 0,001, среднее значение V рассчитывается как 4,99999.
Теперь, если я положу приращение T как 0,0001, Avg V становится 5,00007!

Дальнейшее уменьшение шага до 0,00001 приводит к avg v = 5,00001

Почему это так?

Спасибо.

1

Решение

В базе 2 0.0001 а также 0.001 являются периодическими числами, поэтому они не имеют точного представления. Один из них округляется в большую сторону, а другой округляется в меньшую сторону, поэтому, когда вы их суммируете, вы получаете разные значения.

Это то же самое, что происходит в десятичном представлении, если вы выбираете числа для суммирования соответственно (предположим, что каждая переменная может содержать 3 десятичных знака).
Для сравнения:

a = 1 / 3; // a becomes 0.333
b = a * 6; // b becomes 1.998

с:

a = 2 / 3; // a becomes 0.667
b = a * 3; // b becomes 2.001

оба должны (теоретически) привести к 2 но из-за ошибки округления они дают разные результаты

В десятичной системе, так как 10 делится на простые числа 2 а также 5 только дроби, знаменатель которых делится только на 2 а также 5 могут быть представлены конечным числом десятичных цифр (все остальные дроби являются периодическими), в базисе 2 могут быть точно представлены только дроби, имеющие в качестве знаменателя степень 2. Попробуйте использовать 1.0/512.0 а также 1.0/1024.0 как шаги в вашей петле. Кроме того, будьте осторожны, потому что если вы выберете слишком маленький шаг, у вас может не хватить цифр, чтобы обозначить его в float тип данных (т.е. использовать doubles)

0

Другие решения


По вопросам рекламы [email protected]