2015-07-03 1 views
1

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

Средняя скорость =? X/& Dgr; t

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

Поэтому v = 2t

также сред v = (x2 - x1)/(t2 - t1)

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

Поэтому они средняя 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, рассчитанное значение avg v равно 4.99998.
Теперь, если я нахожу приращение t as 0,0001, avg v становится 5.00007!

Дальнейшее уменьшение приращения к 0,00001 урожайности средн V = 5,00001

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

спасибо.

+0

См. Http://stackoverflow.com/questions/588004/is-floating-point-math-broken, чтобы понять, почему математика с плавающей запятой не может ожидать получения точных результатов. –

+0

Переходим от float к double и видим среднее значение точно 5. Проблема здесь в том, что float не имеет точности. См. Http://stackoverflow.com/questions/2100490/floating-point-inaccuracy-examples. – Robinson

+0

Компьютеры работают в двоичном, а не в десятичном формате. Ошибка округления и распространение ошибок - это тема, о которой вы должны (по крайней мере) знать при использовании с плавающей запятой. Вот ваш код, используя цикл, который будет запускать необходимое количество раз: http://ideone.com/KTzKaP Обратите внимание на окончательное значение после цикла необходимого количества раз. Это распространение ошибок, возникающее при добавлении '0.0001' к поплавке 30 0001 раз. Так как '0,0001' не может быть представлен точно в двоичном формате, вы получаете эту проблему. – PaulMcKenzie

ответ

0

В базе 20.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 может быть r представленное конечным числом десятичных цифр (все остальные фракции являются периодическими), в базе 2 только дробные числа, которые имеют знаменатель, могут быть представлены в виде 2. Попробуйте использовать 1.0/512.0 и 1.0/1024.0 как шаги в вашем цикле.Кроме того, будьте осторожны, потому что, если вы выберете слишком маленький шаг, у вас может не быть достаточно цифр, чтобы представить это в виде данных float (т. Е. Использовать double с)

+0

Есть ли способ улучшить этот цикл, используя только float, т. Е. Улучшить точность, используя только float? Thanx. –

Смежные вопросы