| 
| 
 | Вопрос # 1 646/ вопрос открыт / | 
 |  Приветствую, уважаемые эксперты!Впервые встретился с такой проблемой.
 Программа осуществляет построчное чтение из файла, выделяет из строки числовые данные, преобразует с помощью StrToFloat, вычисляет среднее значение из набора данных и затем отбрасывает 4 и далее знаки после запятой с помощью следующей функции: trunc(1000*Х)/1000.
 Собственно сама проблема: если в результате вычисления среднего получается число с количеством знаков меньше 3 (например как у меня было 6,91), то после преобразования trunc(1000*Х)/1000 на выходе имеем 6,909.
 Замена типов Real на Single избавила такие ошибки в одних значениях, зато аналогичные ошибки появились в других значениях.
 Заранее спасибо.
 
|  |   Вопрос задал: Klipper (статус: Посетитель)Вопрос отправлен: 3 июня 2008, 14:12
 Состояние вопроса: открыт, ответов: 2.
 |  Ответ #1. Отвечает эксперт: ANBsoft Здравствуйте, Klipper!Это связано с двоичнодесятичным преобразованием чисел.
 (не всякое число можно точно преобразовать из двоичной системы в десятичную и наоборот).
 Я обычно использую следующую функцию, где R-округляемое число, N-до какого знака округлять:
 Function RoundANB(R:Double;N:Integer):Double;
 Var f:Integer;
 X:Double;
 Begin
 X:=R;
 for f:=1 to N do X:=X*10;
 X:=Round(X);
 for f:=1 to N do X:=X/10;
 Result:=X;
 End;
 В вашем случае можно делать так trunc(1000*Х+0.01)/1000, этого будет достаточно.
 
|  | Ответ отправил: ANBsoft (статус: Студент)Время отправки: 3 июня 2008, 16:27
 
 |  Ответ #2. Отвечает эксперт: Feniks Здравствуйте, Klipper!В своих проектах я сам мучался с проблемой округлений. Нужна была "бухгалтерская" точность до 1 копейки. Я использовал следующие функции, возможно и вам они помогут:
 
 function RoundEx(const X : Single; I : Byte): Single;
{N := 1 - до целых, 10 - до десятых, 100 - до сотых...}
var
   ScaledFractPart, Temp : Single;
   j, N : byte;
 
begin
   N := 1;
   if I > 0 then
      for j := 1 to I do
          N := N * 10;
   ScaledFractPart := Frac(X) * N;
   Temp := Frac(ScaledFractPart);
   ScaledFractPart := Int(ScaledFractPart);
   if Temp >= 0.5 then ScaledFractPart := ScaledFractPart + 1;
   if Temp <= -0.5 then ScaledFractPart := ScaledFractPart - 1;
   Result := Int(X) + ScaledFractPart / N;
end;
 
function RoundExToStr(const X : Single; I : Byte; bSeparator : boolean = True): String;
var
   j : Byte;
begin
   Result := '';
   for j := 1 to I do
       Result := Result + '#';
   if bSeparator then
      Result := FormatFloat(',0.' + Result, RoundEx(X, I))
   else
      Result := FormatFloat('0.' + Result, RoundEx(X, I));
end;Желаю удачи...
|  | Ответ отправил: Feniks (статус: Бакалавр)Время отправки: 4 июня 2008, 12:17
 
 |  
 Мини-форум вопросаВсего сообщений: 1; последнее сообщение — 3 июня 2008, 16:33; участников в обсуждении: 1. 
|   | ANBsoft (статус: Студент), 3 июня 2008, 16:33 [#1]:Или вместо TRUNC используйте ROUND. На самом деле 6.91 будет представлено примерно так 6,909999,
 поэтому в вычислениях это не критично
 |  Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте. |