Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 09.03.2008, 20:47   #11
B_N
Новичок
Джуниор
 
Регистрация: 18.01.2008
Сообщений: 1,720
По умолчанию

Цитата:
Сообщение от Sibedir Посмотреть сообщение
Так что Int64 подходит куда лучше чем все остальное.
Ладно, Вам виднее. Только придётся придумывать, как бороться вот с этим:

Код:
var
    x1 : real;
    x2 : double;
    x3 : extended;
    i  : cardinal;

begin
    x1 := 1;
    x2 := 1;
    x3 := 1;
    i  := 1;

    writeln('x1: ', x1);
    writeln('x2: ', x2);
    writeln('x3: ', x3);
    writeln('i: ', i);
    writeln;

    x1 := x1 / 3;
    x2 := x2 / 3;
    x3 := x3 / 3;
    i  := round(i  / 3); // Здесь я ВЫНУЖДЕН так писать!
    writeln('x1: ', x1);
    writeln('x2: ', x2);
    writeln('x3: ', x3);
    writeln('i: ', i);
    writeln;


    x1 := x1 * 3;
    x2 := x2 * 3;
    x3 := x3 * 3;
    i  := i  * 3;
    writeln('x1: ', x1);
    writeln('x2: ', x2);
    writeln('x3: ', x3);
    writeln('i: ', i);

    readln;
end.
Код:
x1:  1.00000000000000E+0000
x2:  1.00000000000000E+0000
x3:  1.00000000000000E+0000
i: 1

x1:  3.33333333333485E-0001
x2:  3.33333333333333E-0001
x3:  3.33333333333333E-0001
i: 0

x1:  1.00000000000000E+0000
x2:  1.00000000000000E+0000
x3:  1.00000000000000E+0000
i: 0
B_N вне форума Ответить с цитированием
Старый 09.03.2008, 21:12   #12
Карась
Участник клуба
 
Аватар для Карась
 
Регистрация: 26.10.2007
Сообщений: 1,244
По умолчанию

Код:
x1:  1.00000000000000E+0000  
x2:  1.00000000000000E+0000  
x3:  1.00000000000000E+0000  
i: 1  
  
x1:  3.33333333333485E-0001  
x2:  3.33333333333333E-0001  
x3:  3.33333333333333E-0001  
i: 0  
  
x1:  1.00000000000000E+0000  
x2:  1.00000000000000E+0000  
x3:  1.00000000000000E+0000  
i: 0
Интересно.... Чтото реал врёт....
Умом Россию не понять, пока не выпито ноль пять,
А если выпито ноль пять всё делом кажется не хитрым,
Попытка глубже понимать уже попахивает литром...
Карась вне форума Ответить с цитированием
Старый 09.03.2008, 21:27   #13
_Dmitry
Участник клуба
 
Аватар для _Dmitry
 
Регистрация: 02.09.2007
Сообщений: 1,193
По умолчанию

У меня такого эффекта нет, все значения 3.33333333333333E-0001
Delphi Enterprise v.7.0 (Build 8.1), Windows XP SP2
_Dmitry вне форума Ответить с цитированием
Старый 09.03.2008, 21:45   #14
Карась
Участник клуба
 
Аватар для Карась
 
Регистрация: 26.10.2007
Сообщений: 1,244
По умолчанию

Цитата:
Сообщение от _Dmitry Посмотреть сообщение
У меня такого эффекта нет, все значения 3.33333333333333E-0001
Delphi Enterprise v.7.0 (Build 8.1), Windows XP SP2
+1 TP7.1
Выводил в цикле и делал проверку... 10000 значений и все равны.
Умом Россию не понять, пока не выпито ноль пять,
А если выпито ноль пять всё делом кажется не хитрым,
Попытка глубже понимать уже попахивает литром...
Карась вне форума Ответить с цитированием
Старый 09.03.2008, 21:48   #15
B_N
Новичок
Джуниор
 
Регистрация: 18.01.2008
Сообщений: 1,720
По умолчанию

Да нет, это не реал врёт, а точности не хватает + издержки вывода VP, может быть. MS C++ выводит вот так:
Код:
X1: 1.00000000000000000000e+000
X2: 1.00000000000000000000e+000
I: 1

X1: 3.33333343267440800000e-001
X2: 3.33333333333333310000e-001
I: 0

X1: 1.00000000000000000000e+000
X2: 1.00000000000000000000e+000
I: 0
например. а Гну-фортран для:
Код:
      REAL*4    :: X_SINGLE = 1;
      REAL*8    :: X_DOUBLE = 1;
      REAL*10   :: X_EXTENDED = 1;
      INTEGER*4 :: I = 1;
вообще вот так:
Код:
  1.00000000
  1.00000000000000000
  1.00000000000000000000
           1

  0.33333334
  0.33333333333333331
  0.33333333333333333334
           0

  1.00000000
  1.00000000000000000
  1.00000000000000000000
           0
Просто у single precision (он же real) 22 бита под мантиссу - шесть десятичных знаков. На самом деле, я имел в виду как раз проблему целочисленного деления. Видно же, что после деления и последующего умножения вещественных (в пределах одного порядка) значения сохраняются, ну а у целых......

------------------------------------
Добавлено:
------------------------------------
Сначала извиняюсь за неточность, запамятовал, что тип real и паскале - шестибайтовый.
Точность вещественных чисел выбирают не наобум и не по тому, нравится ли нам, как они представлены в памяти, а по вполне простому критерию: нужно определить, в каком диапазоне будут изменяться величины и какая точность нас интересует в крайних положениях. Например, поставим задачу: иметь шесть точных разрядов при возможных изменениях в пределах двенадцати порядков - для сохранения результатов нам необходимы 12+6=18 десятичных разрядов. Т.е.:

x = 1.23456
y = 1.23456 * 1 000 000 = 1 234 560
z = 1.23456 / 1 000 000 = 0.000 001 234 56

x + y + z = 1 234 561,234 561 234 56

- 18 знаков, делим на log10(2), получаем 59.8 - double нас не устроит, а extended для работы достаточно. Любое число, имеющее в нормальной форме шесть значащих цифр будет иметь также шесть верных значащих цифр (возможно с округлением перед выводом) после операций, результаты которых не выходят из допустимой области по порядку величины. Проверим это для нескольких типов вещественных чисел:
Код:
var
  x, y, z, sum : single;
//  x, y, z, sum : real;
//  x, y, z, sum : double;
//  x, y, z, sum : extended;
begin
    x := 1.23456;
    y := x * 1000000;
    z := x / 1000000;
    sum := x + y + z;

    writeln('  x = ', x : 0 : 20);
    writeln('  y = ', y : 0 : 20);
    writeln('  z = ', z : 0 : 20);
    writeln('------');
    writeln('sum = ', sum : 0 : 20);
    writeln('------');
    writeln('  x = ', sum - y - z : 0 : 20);
    writeln('  y = ', sum - x - z : 0 : 20);
    writeln('  z = ', sum - y - x : 0 : 20);
    readln;
end.
single: (точность 23 бита - 7 десятичных разрядов)
Код:
  x = 1.234560012817382810
  y = 1234560.000000000000000000
  z = 0.000001234560045305
------
sum = 1234561.250000000000000000
------
  x = 1.249998765439954700
  y = 1234560.015438752620000000
  z = 0.015439987182617188
уцелело только максимальное значение.

real: (39 бит)
Код:
  x = 1.234560000000783480
  y = 1234560.000000000000000000
  z = 0.000001234560000000
------
sum = 1234561.234561920170000000
------
  x = 1.234560685606015620
  y = 1234560.000000685610000000
  z = 0.000001920165232150
максимальное и среднее значения верны, но, как и в предыдущем случае, значение на нижней границе диапазона уничтожено.

double (52 разряда):
Код:
  x = 1.234560000000000100
  y = 1234560.000000000000000000
  z = 0.000001234560000000
------
sum = 1234561.234561234480000000
------
  x = 1.234559999919770060
  y = 1234559.999999999920000000
  z = 0.000001234479769963
максимальное и среднее значения (с учетом округления) верны, минимальное - нет

extended (63 разряда):
Код:
  x = 1.234560000000000000
  y = 1234560.000000000000000000
  z = 0.000001234560000000
------
sum = 1234561.234561234560000000
------
  x = 1.234560000000032970
  y = 1234560.000000000000000000
  z = 0.000001234560032972
как и предполагалось, поскольку сумма хранит неискаженное число, верны все значения. В ряде случаев, в зависимости от порядка операций, может потребоваться округление (для вывода значений).

Последний раз редактировалось B_N; 10.03.2008 в 02:53.
B_N вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
как сложить два числа с плавающей точкой forsy Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM 19 29.03.2010 02:15
Преобразование числа в строку )Игнат( Общие вопросы Delphi 6 06.07.2008 09:32
Сравнение чисел с плавающей точкой ? Ulex Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM 11 12.04.2008 21:14
Числа с плавающей точкой Blondinka Общие вопросы Delphi 8 21.09.2007 11:32