Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.07.18;
Скачать: CL | DM;

Вниз

Интересная проблема с 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;
Скачать: CL | DM;

Наверх




Память: 0.49 MB
Время: 0.034 c
8-1081456553
CAHEK
2004-04-09 00:35
2004.07.18
SWF из ресурса???


1-1088881014
Vasya.ru
2004-07-03 22:56
2004.07.18
При нажатии на крестик в правом верхнем углу выводить окно?


1-1089025841
killer
2004-07-05 15:10
2004.07.18
Раскрыто ли PopupMenu


3-1088078300
Эдик
2004-06-24 15:58
2004.07.18
Индексы в Local SQL


14-1088587668
Amit
2004-06-30 13:27
2004.07.18
Вот блин, люди вы даёте >:-(