Официальный сайт студ.городка НГТУ
Программирование и БД » Мистика в вычислениях 

#1  28.02.06 17:32

Мистика в вычислениях

почему-то билдер в любом раскладе при вычислении такого выражения дает такой результат:
426.6432 - (int)426.6432 = 0.643200000000014
числа произвольные написал, но смысл думаю ясен
задача вообще-то по моделированию. требуется получить последовательность СЧ с помощью датчика Лемера
при любой точности (хоть float, хоть long double) последовательность зануляется на 8-й - 10-й итерации, как-будто комп сам подбирает нужные числа...
а вот выражение для датчика Лемера:
X[i+1] = X[i]*3456 - (int) (X[i]*3456)
X[0] = 0.12345 (можно в принципе и 0.123456789 взять)
потратил вчера на это 3 часа и не понял откуда эти лишние 0,000000000000014 берутся
а вот и код:
    double X[100];
    memset(X, 0, sizeof(X));
    X[0] = 0.12345;
    ListBox1->Items->Add(X[0]);
    for (int i = 1; i < 100; i++)
    {
        X[i] = X[i-1]*3456.0 - (int) (X[i-1]*3456.0);
        ListBox1->Items->Add(X[i]);
    }

Offline

#2  28.02.06 18:11

Re: Мистика в вычислениях

а это проблемма хранения данных  типа float, ты посмотри как он хранится и все станет ясно...я про число, експоненту..и что там еще было подзабыл))

Offline

#3  28.02.06 18:31

Re: Мистика в вычислениях

Stell Hawk написал(а):

експоненту..

нарна, мантисса, а не экспонента?

Offline

#4  28.02.06 20:09

Re: Мистика в вычислениях

гыы.... это такой прикол у Билдера есть... я в свое вермя его тоже обнаруживал... ничего с этой ошибкой не поделаешь, ошибка она просто появляется и все. Причем проявляется она в последних 2-х разрядах (переходит ли на 3-й с конца - помню)....

даже если в Билдере просто взять вот такой вот код:

Код::

double A = 1;
for(int i = 0; i < 1000 ;i++)
 A+=1;

То высока вероятность, что А после цикла не будет равняться 1001.....
Избежать эту ошибку (по крайней мере, я больше ни в каких случаях этой ошибки не встречал) можно уходом от последовательного складывания double в цикле к умножению на какой-то множитель....

Offline

#5  28.02.06 20:39

Re: Мистика в вычислениях

собсна, по этой же причине нельзя проверять на просто равенство 2 вещественных числа...

Offline

#6  28.02.06 21:36

Re: Мистика в вычислениях

Хм... а если мутить проект не в билдере, ошибка не появится? Или это все-таки связано именно с хранением чисел с плавающей точкой?
и кстати если поставить где-нибудь брейкпойнт в проекте и в watchlist'е написать что-нибудь типа 426.1-426, то результат, как говорится, налицо :)
и даже без всяких циклов...
и почему-то эта незначительная ошибка с огромной точностью сводит ряд СЧ к нулю :)

Offline

#7  28.02.06 22:16

Re: Мистика в вычислениях

simplex,

simplex написал(а):

а если мутить проект не в билдере, ошибка не появится?

скорее всего появится. В любом нормальном учебнике по программированию указано, что нельзя напрямую сравнивать 2 вещественных числа...

в этом примере - юзай целочисленные типы как числа с фиксированной точкой. Плавающая тебе здесь не нужна...
Если long будет не достаточно (19 разрядов), то определи свой тип, более длинный...

В VS.NET есть тип Currency, он хранит 96 бит числа....

Offline

#8  28.02.06 23:22

Re: Мистика в вычислениях

в билдере есть int64

Offline

#9  01.03.06 01:31

Re: Мистика в вычислениях

otaku написал(а):

в билдере есть int64

сие есть long int :)

Offline

#10  01.03.06 01:44

Re: Мистика в вычислениях

Andron_ написал(а):

сие есть long int :)

нет лонг это 32 бита
а тот 64 бита
тро бишь в два раза больше
и пишеться как __int64

Исправлено otaku (01.03.06 01:47)

Offline

#11  06.03.06 01:28

Re: Мистика в вычислениях

целочисленные переменные хранятся в памяти в двоичном виде: x0*2^0+x1*2^1+x3*2^2+x4*2^3. причем, число это x4x3x2x1x0 (двоичный вид). Дробные числа хранятся по-другому: x0*1/2^1+x1*1/2^2+x2*1/2^3+x3*1/2^4.... т.е. последовательным суммированием дробей. В итоге получается, что никогда не получить точного значения 0.32413245 - будет лишь приближение 0.32413245111111 (к примеру). Приводя целое к дробному получаем, такое, что появляется некоторый хвост, от которого не избавиться никогда. Выход - округление до нужного разряда после вычислений.

Offline

#12  07.03.06 09:19

Re: Мистика в вычислениях

Если вы хотите узнать как на самом деле хранятся числа с плавающей запятой, прочтите IEEE Standard 754-1985.

Offline

#13  14.03.06 08:24

Re: Мистика в вычислениях

Да с хранением уже все ясно... Теперь мучает другой вопрос: есть тип Currency (с фиксированной точкой, 4 разряда в дробной части). Если эта точность меня не устраивает и мне надо 8, то, как уже советовали, можно описать свой тип данных наподобие Currency. Как это сделать? Примерчик кинули бы... или ссылочку

Offline

#14  14.03.06 09:40

Re: Мистика в вычислениях

цифры хранишь в массиве, длина массива  будет твоя точность, мантису храни в отдельной переменной, ну и реализуйц операции  по разрядные как в начальной школе!

Offline

#15  14.03.06 09:45

Re: Мистика в вычислениях

otaku, а не проще уже полученный результат округлять?

Offline

#16  14.03.06 14:11

Re: Мистика в вычислениях

akse написал(а):

otaku, а не проще уже полученный результат округлять?

каким образом?
человек же сказал что ему не хватате точности в разрядах, других способов насколько я знаю не существует

Offline

Программирование и БД » Мистика в вычислениях 

ФутЕр:)

© Hostel Web Group, 2002-2025.   Сообщить об ошибке

Сгенерировано за 0.045 сек.
Выполнено 14 запросов.