|
Вопрос # 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,
поэтому в вычислениях это не критично
|
Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.
|