![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Мат, округлние [D4]
pasha_golub © (2004-10-28 14:59:00)Люди, добрые подскажите параметр для FPU 8087, которое нужно кинуть в Set8087CW для того, чтобы округление было не банковским, а математическим. Спасибо.
pasha_golub (2004-11-04 12:04:00) [1]Defunct © (29.10.04 18:43) [50]
Спасибо огромное, значит я не ошибался.
Defunct (2004-10-29 18:43:00) [2]> pasha_golub © (29.10.04 12:20) [47]
> Потому и задал его тут.
Округлений просто море, потому что округление выполняет уменьшение точности, а как вы сами понимаете уменьшить точность можно как угодно. Выбирайте то, что нужно именно вам.
Мат округление, бухгалтерское, до четного, и т.п.
> pasha_golub © (29.10.04 12:40) [49]
http://search2.intel.com/corporate/default.aspx?q=Intel+IA-32+software+developers+manual+download
Там три части vol 1-3.
вторая часть "instruction set reference" в двух книгах по ~600стр. vol 2A, vol 2B
pasha_golub (2004-10-29 12:40:00) [3]Еще вопрос не по теме. Подскажите, где взять мануал по АСМу с сайта Интела, а то я как-то не нашел, видно руки...
Romkin (2004-10-29 12:30:00) [4]Все очень просто: Округляют к четному, дабы избежать дрейфа при операциях вида
1 + 0.5 - 0.5 + 0.5 - 0.5 ... Если каждый раз округлять, то "к четному" будет держать 2. А "школьное" - увеличиваться!
pasha_golub (2004-10-29 12:20:00) [5]Ого, мужики развели.
Вообщем, на самом деле это вопрос тоже не мой, а друга. И он меня тоже ввел в пучину сомнений и раздумий. Потому и задал его тут. А оказалось все не так просто. Гы
pasha_golub (2004-10-29 12:17:00) [6]Ого, мужики развели.
Вообщем, на самом деле это вопрос тоже не мой, а друга. И он меня тоже ввел в пучину сомнений и раздумий. Потому и задал его тут. А оказалось все не так просто. Гы
GuAV (2004-10-29 02:17:00) [7]Defunct © (29.10.04 1:13) [43]
32124323134998536792.5 (на нем уже все функции неправильно округляют).
:)
Точнее сказать такое число просто не может быть представленно с точностью выше целых. Т.е. .5 никуда не помещается. И функции уже ни при чём.
Defunct © (29.10.04 1:13) [43]
Eсли же работать с огромными числами (правильнее сказать с очень высокой точностью больше 50 знаков в числе), тогда ни ваша функция, ни функция Verg не помогут.
Названные функции работают при точности больше 50 двоичных знаков. О больше чем 64 знаках речь конечно идти не может - это уже действительно предел точности FPU.
Verg (2004-10-29 01:51:00) [8]
> Давайте применим это правило к числам около нуля.
>
Давайте
0.5 + (-0.5) = 0
Что нам даст "жлобское" округление слагаемых? 1 + (-1) = 0 - тот же 0
Так, а теперь round( x + E) -> 1 + 0 = 1
Так какое же округление на самом деле "жлобское"?
Defunct (2004-10-29 01:13:00) [9]GuAV © (29.10.04 01:02) [41]
Понимаете, особой разницы нет на каком знаке произойдет сбой
или на числе 212432313499856792.5 или на числе 32124323134998536792.5 (на нем уже все функции неправильно округляют). Если просто работать с обычными числами (не гигантскими) тогда достаточно обойтись с помощью [12]. Eсли же работать с огромными числами (правильнее сказать с очень высокой точностью больше 50 знаков в числе), тогда ни ваша функция, ни функция Verg не помогут. Но, как правило, такая точность нигде не требуется.
Defunct (2004-10-29 01:02:00) [10]Verg © (29.10.04 00:41) [39]
> Можете еще с excel-ом поиграться.
Не, там жлобское округление.
если кредит (отрицательные числа) забирать больше.
если долг - отдавать меньше ;)
Есть еще бухгалтерское округление - обрезать до целого
(чтобы не платить лишнего) ;>
> Образует какое-то "альтернативное" понятие математического округления :))
Как в советской школе учили. округлять к большему. ;>
в яндексе правило округления отрицательных чисел должно быть. Там оно как в советской школе - к большему.
GuAV (2004-10-29 01:02:00) [11]Ну так, я и говорю, что Вы не можете написать E для кода где входные данные заранее неизвестны, поэтому при использовании Вашей функции нужно учитывать эти ограничения.
Это ни как не увязывается с
> "Программист! ДЕЛАЙ ВСЕ ПРОЩЕ".
Defunct (2004-10-29 00:53:00) [12]GuAV © (29.10.04 00:35) [38]
Извините, но вы показываете свое неумение слушать.
X:=212432313.4998567925;
Конкретно в этом числе порядок наименьшего значащей цифры (5) = 10(-10). Соответственно E = 10(-11).
Все упирается в точность.
Опять же
Z:=212432313499856792.5;
при E=0.01 округлит верно.
для полноты картины надо бы добавить еще и
Y = 3212432313499856792.5;
В общем если вы пытаетесь показать ограниченность мантиссы, так с этим никто не спорит.
Verg (2004-10-29 00:41:00) [13]Можете еще с excel-ом поиграться. Тот использует математическое округление без правила "четной цифры". Функция =ОКРУГЛ().
А
>В математике все же округление идет к большему целому.
> Const E = 0.000000000001;
>
> Round( Число + E );
Образует какое-то "альтернативное" понятие математического округления :))
GuAV (2004-10-29 00:35:00) [14]Defunct © (28.10.04 23:33) [32]
Док-во - конкретный пример где такое округление даст сбой
procedure TForm1.FormCreate(Sender: TObject);
var X, X1, Z, Z1: Extended; S: string; OldMode: TFPURoundingMode;
begin
Z:=212432313499856792.5;
X:=212432313.4998567925;
Memo1.Lines.Add('Defunct');
Z1:=Round(Z + 0.001);
X1:=Round(X + 0.001);
Memo1.Lines.Add(FloatToStrF(Z1, ffFixed, 22, 2));
Memo1.Lines.Add(FloatToStrF(X1, ffFixed, 22, 2));
Memo1.Lines.Add('Verg');
Z1:=Trunc(Z) + Trunc (Frac(Z) * 2);
X1:=Trunc(X) + Trunc (Frac(X) * 2);
Memo1.Lines.Add(FloatToStrF(Z1, ffFixed, 22, 2));
Memo1.Lines.Add(FloatToStrF(X1, ffFixed, 22, 2));
Memo1.Lines.Add('GuAV');
OldMode := SetRoundMode(rmDown);
try
Z1:=Round(Z + 0.5);
X1:=Round(X + 0.5);
finally
SetRoundMode(OldMode);
end;
Memo1.Lines.Add(FloatToStrF(Z1, ffFixed, 22, 2));
Memo1.Lines.Add(FloatToStrF(X1, ffFixed, 22, 2));
end;
Defunct (2004-10-29 00:31:00) [15]Verg © (29.10.04 00:04) [36]
ага нашел.
Округление состоит в отбрасывании, точнее в замене нулями, всех цифр, стоящих правее цифры данного разряда. Если при этом первой из отбрасываемых цифр является 0, 1, 2, 3 или 4 , последняя остающаяся цифра не меняется; если же первой из отбрасываемых цифр окажется 5, 6, 7, 8 или 9 , последняя остающаяся цифра увеличивается на 1
Давайте применим это правило к числам около нуля.
-0.6 = -1
-0.5 = -1
-0.4 = 0
-0.3 = 0
-0.2 = 0
-0.1 = 0
0 = 0
0.1 = 0
0.2 = 0
0.3 = 0
0.4 = 0
0.5 = 1
Получается почему-то 9 нулей хотя должно быть 10. ведь целое складывается из десяти десятых, а не из девяти.
Выводы:
1. 0 - не целое число (но это не так).
2. метод округления указан не точно. И действительно в приведенной статье нет правила округления отрицательных чисел.
Verg (2004-10-29 00:04:00) [16]
> [34] Defunct © (28.10.04 23:56)
http://www.sgu.ru/ie/mehmat/matin/R1-4.htm
False_Delirium (2004-10-29 00:04:00) [17]Defunct © (28.10.04 23:56) [34]
Математическое округление -1.5 даёт -1
и кто говорит обратное - идёт в туман :))
Defunct (2004-10-28 23:56:00) [18]> Verg
> http://www.sgu.ru/ie/mehmat/matin/
Извини, но я там не нашел ни слова про округление..
То, что по второй ссылке -1.5 = -2 я поверю наслово.
sniknik (2004-10-28 23:54:00) [19]> а на 2.001 что получим?
обана, а мужики то не в курсе. ;о)
сорри, действительно ерунда получилась.
Defunct (2004-10-28 23:33:00) [20]GuAV © (28.10.04 22:15) [26]
> Я уже доказал.
Не не доказал.
Док-во - конкретный пример где такое округление даст сбой, а ваш способ и ф-ция Verg округлит правильно.
> Вот допустим ххх.5 и .5 в последнем знаке, прибавление 0.1 не
> изменит число, и если оно нечётноё, оно округлится в меньшую
> сторону ка и просто Round.
Давайте без допустим. Допустим в мантиссу не влазит дробная часть вообще. В общем это чушь а не доказательство.
> Вот и получается: как не крути, а ОКРУГЛЕНИЕ(-1.5) = -2
В математике все же округление идет к большему целому.
Просто и со вкусом:
Const E = 0.01;
procedure TForm1.Button8Click(Sender: TObject);
begin
ShowMessage( Format(']-2.5[ = %D',[ Round(-2.5 + E) ] ));
ShowMessage( Format(']-1.5[ = %D',[ Round(-1.5 + E) ] ));
ShowMessage( Format(']1.5[ = %D',[ Round(1.5 + E) ] ));
ShowMessage( Format(']2.5[ = %D',[ Round(2.5 + E) ] ));
end;