Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Странности с математикой (real, extended)


alex989 ©   (2009-04-20 20:47:00) 

Доброго времени суток!

Мне нужно составить программу, заполняющую таблицу вида:

X| | | |
Y| | | |

по функции: Y = A * sin(2 * pi * f * X)
числа A и f - постоянные, X меняется с определенным шагом. Я сделал массив 2 строки, 100 столбцов (с запасом =)) И пытаюсь его заполнить, но выходит ахинея.
вот код:

program Project3;

{$APPTYPE CONSOLE}

uses
 SysUtils, Math;

var
 Farr: array [0..1, 0..100] of extended;
 A, f, t, x, d: extended;
 j: integer;
 s: string;

begin
 A := 5;
 f := 50;
 t := 5;
 d := 0.1; // шаг
 j := 0; // счетчик для массива
 x := d;
 repeat
   Farr[0,j] := x;
   Farr[1,j] := A * sin(2 * pi * f * x);
   x := x + d;
   j := j + 1;
   writeln((FloatToStr(Farr[0,j])+'   '+FloatToStr(Farr[1,j])+#10#13));
 until x >= t;

 readln(s); // чтобы окошко не закрылось
end.


Проблемы следующие:
неправильно рсчитывается элемент массива, т.е. A * sin(2 * pi * f * x), если посчитать на калькуляторе винды, числа абсолютно разные.
следующая непонятка, если поменять тип данных на real (вместо extended), результаты будут другими, но опять же - неправильными...
и наконец функция printf выводи нули, хотя массив числами заполняется (правда, неправильно).. может я как-то не так использую FloatToStr?

Заранее спасибо!


12   (2009-04-21 12:14:00) [1]

> 0,5 оно в любой двоичной Африке 0,5, а вот 0,1 уже от размера
> двоичной Африки зависит.
а от чего конкретно?

от того же, что и 1/3 для человека
1/3 = 0.(3)
в периоде, для человека понятно, а вот записть это конечной дробью можно только примерно.
0.333333 или 0.333333333333333333333 или
второе точнее первого
Если больше ячеек для хранения числа, то и представление точнее. А, значит, и разный результат
0.333333 < 0.333333333333333333333
т.е.
1/3 <> 1/3,  для разных Африк


Jeer   (2009-04-21 10:05:00) [2]


> потому я и взял 0,1


Слишком крупный шаг.
Чтобы "увидеть" синусоиду надо сделать мельче шаг по времени.


alex989   (2009-04-21 08:19:00) [3]


> На первой итерации цикла из [0], использование Real дает
> ответ 8,71*10^-15, использование Extended 5,42*10^-19. Разница
> в 4 раза для вас недостаточно огромна?


вот и я про тоже :(

x (или t-по формуле) - это время, измерять его просто в секундах не получится, т.к. частота сигнала 50 Гц, потому я и взял 0,1


> 0,5 оно в любой двоичной Африке 0,5, а вот 0,1 уже от размера
> двоичной Африки зависит.

а от чего конкретно?


alex989   (2009-04-21 08:15:00) [4]

Спасибо за ответы!
Насчет вывода нулей понятно.

Считаю я такую вешь (кто шарит в электронике, поймет):
U = A * sin(2*pi*f*t)

A-амплитуда сигнала, f - частота, t - время (как я думаю, t и есть координата x)

нужно заполнить таблицу, чтобы нарисовать по ней синусоиду. Но что-то не вяжется тут...


> Может дело в том, что угол в функции рассчитывается в радианах?

можно по-подробнее?


alex989   (2009-04-21 08:15:00) [5]

Спасибо за ответы!
Насчет вывода нулей понятно.

Считаю я такую вешь (кто шарит в электронике, поймет):
U = A * sin(2*pi*f*t)

A-амплитуда сигнала, f - частота, t - время (как я думаю, t и есть координата x)

нужно заполнить таблицу, чтобы нарисовать по ней синусоиду. Но что-то не вяжется тут...


> Может дело в том, что угол в функции рассчитывается в радианах?

можно по-подробнее?


Servy   (2009-04-21 04:25:00) [6]

> Разница в 4 раза

Прошу прощения, на 4 порядка, в ~10000 раз.


Servy   (2009-04-21 04:23:00) [7]

> я и не говорил, что они по размеру совпадают!


Зато вы говорили:


> А с REAL и EXTENDED разница может быть лишь в том случае
> когда {$REALCOMPATIBILITY ON},



> От смены 8 или 10 байтной переменной огромной погрешности
> в вычислении обыкновенного синуса быть не может!


На первой итерации цикла из [0], использование Real дает ответ 8,71*10^-15, использование Extended 5,42*10^-19. Разница в 4 раза для вас недостаточно огромна?


> 0.5 оно и в Африке 0.5!

0,5 оно в любой двоичной Африке 0,5, а вот 0,1 уже от размера двоичной Африки зависит.


Германн   (2009-04-21 01:37:00) [8]


> Смысл не в том что 8 или 10 байт, а в том что 0.5 оно и
> в Африке 0.5!

А вот нифига! В Африке 0.5 может и не быть 0.5!
Да и не только в Африке! :)


FireMan_Alexey   (2009-04-21 00:26:00) [9]


> Servy ©   (20.04.09 23:11) [6]

А я и не говорил, что они по размеру совпадают!
Я говорил, что при вычислении, выше описанной формулы, глобальной разницы быть не может!

Смысл не в том что 8 или 10 байт, а в том что 0.5 оно и в Африке 0.5!
От смены 8 или 10 байтной переменной огромной погрешности в вычислении обыкновенного синуса быть не может!
Погрешность в вычислении можно заметить если использовать 4 байтный (сингл) и 8 байтную (даблу). Я замечал погрешность в 1Е-08, а автор пишет:


> если поменять тип данных на real (вместо extended), результаты
> будут другими


Ну если считать показатели где то в 18 цифре после запятой, то я соглашусь с вашими аргументами, но такая точность нужна лишь в космосе или 3Д игрушке на больших расстояниях! Ну или в Автокаде...


Servy   (2009-04-20 23:11:00) [10]

> А с REAL и EXTENDED разница может быть лишь в том случае
> когда {$REALCOMPATIBILITY ON}, тогда на реал 6 байт выделяется,
> а так 8, точно как у дабла! :)


Неправда ваша, Extended не тоже самое что Double.


Type     Range                              Significant digits   Size in bytes
...
Double   5.0 x 10^-324 .. 1.7 x 10^308      15-16                8
...
Extended 3.6 x 10^-4951 .. 1.1 x 10^4932    19-20                10
...


Из стандартной справки. Так что, кое какая разница между Real и Extended присутствует в любом случае ^_^


FireMan_Alexey   (2009-04-20 21:57:00) [11]

А с REAL и EXTENDED разница может быть лишь в том случае когда {$REALCOMPATIBILITY ON}, тогда на реал 6 байт выделяется, а так 8, точно как у дабла! :)


FireMan_Alexey   (2009-04-20 21:52:00) [12]

Да вообще формула не понятная!
один градус для Дельфийного синуса = (Пи/180). А потом умножай на нужный угол и все! :)
Зачем прибавлять 0.1 когда каждый раз умножаешь на 50? Прибавляй 0.5, а 50 в топку!
И вообще че ты считаешь?


Servy   (2009-04-20 21:27:00) [13]


>   Farr[0, j] := x;
>   Farr[1,j] := A * sin(2 * pi * f * x);
>   x := x + d;
>   j := j + 1;
>   writeln((FloatToStr(Farr[0, j])+'   '+FloatToStr(Farr[1,
> j])+#10#13));


Ты выводишь элемент массива, которому не было присвоено значение. Так как массив - глобальная переменная, то там изначально нули, которые ты и видишь.


> если посчитать на калькуляторе винды, числа абсолютно разные

Конкретные примеры в студию. Возможно, в калькуляторе у тебя Sin считается от аргумента в градусах, тогда как делфевый Sin ждет аргумента в радианах (что описано в справке).


> readln(s); // чтобы окошко не закрылось


Readln без параметров ждет нажатия ентера, s тут лишняя.


FireMan_Alexey   (2009-04-20 21:25:00) [14]

Увеличивай J после вывода, а не до!!!


FireMan_Alexey   (2009-04-20 21:15:00) [15]

Может дело в том, что угол в функции рассчитывается в радианах ?


Наверх

Титульная страница Поиск, карта сайта Написать письмо