Форум: "Основная";
Текущий архив: 2004.07.18;
Скачать: [xml.tar.bz2];
ВнизИнтересная проблема с SimpleRoundTo Найти похожие ветки
← →
Song © (2004-07-04 12:35) [0]Читаем хэлп:
*************
Rounds a floating-point value to a specified digit or power of ten using asymmetric arithmetic rounding.
The following examples illustrate the use of SimpleRoundTo:
....
....
Expression Value
SimpleRoundTo(1234567, 3) 1234000
SimpleRoundTo(1.234, -2) 1.23
SimpleRoundTo(1.235, -2) 1.24
SimpleRoundTo(-1.235, -2) -1.23
**************************
Как видно пример с 1.235 прокатывает и 1.235 округляется правильно в 1.24 согласно школьным правилам округления.
Я у себя делаюResult:=SimpleRoundTo(Result,-2);
при Result равным 1.175 и получаю 1.17, а не 1.18.
ПОЧЕМУ? :)
Это предистория. Далее я написал новый проект вот так:procedure TForm1.Button1Click(Sender: TObject);
Function Pr: Double;
Var t: Integer;
k: Double;
Begin
Result:=4.7;
k:=0.5;
Result:=Result * k;
For t:=1 to 1 Do Result:=SimpleRoundTo(Result * 0.5,-2);
End;
begin
ShowMessage(FloatToStr(Pr));
end
Здесь работает. Но ПОЧЕМУ-ТО не работает в моей программе.
Уже отчался найти багу, поэтому вывожу всю функцию.Function NewK(Format,n: String): Double;
{ Функция вычисления коээфициента увелечения многополосных газет
по новому формату }
Var t,z,Polosn: Integer;
k: Double;
Begin
Result:=-1;
try
Polosn:=StrToInt(n);
except
MessageDlg("Неизвестная полосность. Коэффициент увеличения массы многополосных газет " +
"не может быть определён.",mtError,[mbOk],0);
Exit;
end;
{ Высчитываем коээфициент увеличения массы многополосных газет
исходя из коэффициента для базового формата А2 }
Case Polosn OF
0..5: Result:=1;
6..13: Result:=1.2;
14..29: Result:=1.8;
30..31: Result:=3;
32..41: Begin
Result:=3.5;
IF Polosn > 32 then For t:=33 to Polosn Do
IF not Odd(t) then Result:=Result + 0.2;
End; {IF}
{ Для полосности больше 42 }
else Begin
Result:=4.4;
IF Polosn > 42 then For t:=43 to Polosn Do
IF not Odd(t) then Result:=Result + 0.1;
End; {else}
End; {Case}
{ Получаем текущий формат }
try
z:=StrToInt(Format);
except
MessageDlg("Неизвестный формат (" + Format + "). Коэффициент увеличения массы " +
"многополосных газет будет взят как для формата А2.",mtError,[mbOk],0);
Exit;
end;
{ Если формат больше А2, то корректируем его }
IF z > 2 then
Begin
Case Polosn OF
0..5: k:=0.6;
6..29: k:=0.7;
30..33: k:=0.52;
else k:=0.5;
End; {Case}
{ Определяем базовый коэффицицент для формата А3 }
Result:=Result * k; // ТА САМАЯ Строчка :))
{ Корректируем для более малых форматов, начиная с А4 }
IF z > 3 then For t:=4 to z Do Result:=SimpleRoundTo(Result * 0.5,-2);
End; {IF}
End;
Вызоваем её с параметрами NewK("4","48")
После строчки Result:=Result * k; имеем в Result 2.35
Далее умножаем 2.35 * 0.5 и получаем 1.175 и округляем до двух знаков. Должно получаться 1.18, а получается в Result 1.17 :(
← →
Alx2 © (2004-07-04 12:38) [1]>Song © (04.07.04 12:35)
Внимательно пост не читал. Но флаг округления в сопроцессоре учитывается?
← →
Alx2 © (2004-07-04 12:42) [2]Имею в виду x87 FPU Control Word биты 10 и 11
← →
Song © (2004-07-04 12:49) [3]Я его нигде не изменял.
Есть проект 1 и проект 2.
В проекте 1 не работает
В проекте 2 работает. :)
В проекте 1 никаких Set8087CW или SetRoundMode не используется. Проект 2 создан как обычно из ИДЕ :)
← →
Song © (2004-07-04 12:51) [4]Даже если перенести всю эту функцию из нерабочего проекта 1 в рабочий проект 2, то она всё-равно не работает. Вообщем, имеем интересную ситуацию: две одинаковых по смыслу и по используемому алгоритму функции, но одна работает, вторая - нет. :)
← →
Alx2 © (2004-07-04 12:53) [5]А если его все-таки посмотреть и сравнить? Мало ли кто его передернуть мог...
← →
Song © (2004-07-04 12:55) [6]Ну проект 1 - это я сильно сказал. Под проектом 1 я имею ввиду ту процедурку Procedure Button1Click, которуя я написал для теста. Она работает. А NewK() - нет.
Когда я переношу NewK в проект с Button1Click, тоже самое: последняя работает, NewK - нет.
← →
Alx2 © (2004-07-04 13:10) [7]Все-таки я бы сверил флаг
← →
Song © (2004-07-04 19:02) [8]Вопрос решил.
Оказалось дробные числа каверзные :)
В переменной было
1.17499999999999
поэтому когда округляешь по 2-му знаку, он совершенно правильно округляет в 1.17
поэтому нужно сначала по 3-ему, а потому по 2-му ))
← →
Anatoly Podgoretsky © (2004-07-04 19:07) [9]Song © (04.07.04 19:02) [8]
Это только для случая если 1.17499999999999 неверное из за относительной точности, а если число реальное, то такое округление будет неверным, вместо 1,17 будет 1,18
← →
Anatoly Podgoretsky © (2004-07-04 19:12) [10]Song © (04.07.04 19:02) [8]
Если просматривать в отладчике, то надо принудительно указывать тип Extended ина отображение урезано до 15 символов
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2004.07.18;
Скачать: [xml.tar.bz2];
Память: 0.48 MB
Время: 0.046 c