Экспертная система Delphi.int.ru

Сообщество программистов
Общение, помощь, обмен опытом

Логин:
Пароль:
Регистрация | Забыли пароль?

Delphi.int.ru Expert

Другие разделы портала

Переход к вопросу:

#   

Статистика за сегодня:  


Лучшие эксперты

Подробнее »



Вопрос # 1 646

/ вопрос открыт /

Приветствую, уважаемые эксперты!
Впервые встретился с такой проблемой.
Программа осуществляет построчное чтение из файла, выделяет из строки числовые данные, преобразует с помощью StrToFloat, вычисляет среднее значение из набора данных и затем отбрасывает 4 и далее знаки после запятой с помощью следующей функции: trunc(1000*Х)/1000.
Собственно сама проблема: если в результате вычисления среднего получается число с количеством знаков меньше 3 (например как у меня было 6,91), то после преобразования trunc(1000*Х)/1000 на выходе имеем 6,909.
Замена типов Real на Single избавила такие ошибки в одних значениях, зато аналогичные ошибки появились в других значениях.
Заранее спасибо.

Klipper Вопрос ожидает решения (принимаются ответы, доступен мини-форум)

Вопрос задал: 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

ANBsoft (статус: Студент), 3 июня 2008, 16:33 [#1]:

Или вместо TRUNC используйте ROUND.
На самом деле 6.91 будет представлено примерно так 6,909999,
поэтому в вычислениях это не критично

Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.

Версия движка: 2.6+ (26.01.2011)
Текущее время: 22 февраля 2025, 11:45
Выполнено за 0.02 сек.