Доброго времени суток, Уважаемые жители Королевства!
Имеем Delphi 10.3 Version 26.0.32429.4364 и функцию Trunc
При передаче в функцию сложновычисляемого значения наблюдается странно поведение. Пример тестового App:
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
TObj = class
class function Discrete: Currency;
end;
TOrder = record
Vol: Currency;
Amount: Currency;
Price: Currency;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
var
O: TOrder;
c: Currency;
begin
O.Price := 48;
O.Amount := 96.48;
c := TObj.Discrete;
//Ожидаемый результат O.Vol = 2,01 но не все так просто
//В одну строку
O.Vol := Trunc(O.Amount / O.Price / c) * c; // НЕВЕРНО!!!!!!!! O.Vol = 2
//"с" заменена на "прибитое гвоздями" значение
O.Vol := Trunc(O.Amount / O.Price / 0.01) * c; // Верно O.Vol = 2,01
//Последовательное раздельное вычисление
O.Vol := O.Amount / O.Price / c;
O.Vol := Trunc(O.Vol) * c; // Верно O.Vol = 2,01
Application.Terminate;
end;
{ TObj }
class function TObj.Discrete: Currency;
begin
Result := 0.01;
end;
Что происходит с функцией? Ничего не понимаю...
Заранее спасибо за ответы
Уважаемые авторы вопросов! Большая просьба сообщить о результатах решения проблемы на этой странице. Иначе, следящие за обсуждением, возможно имеющие аналогичные проблемы, не получают ясного представления об их решении. А авторы ответов не получают обратной связи. Что можно расценивать, как проявление неуважения к отвечающим от автора вопроса.
//В одну строку
O.Vol := Trunc(O.Amount / O.Price / c) * c; // НЕВЕРНО!!!!!!!! O.Vol = 2
В этом случае то, что передается в Trunc, приводится к типу с плавающей точкой, которое на самом деле получилось чуть меньше 201 (например, 200.999999999999994). Думаю, что если напишете так:
Тип Currency это тип с четырьмя знаками после запятой, и он себя ведет не так, как числа с плавающей точкой.
Когда вы "прибиваете гвоздями" значение, то ваше 0.01 на самом деле тоже чуть меньше 0,01 (например, 0.009999999999997). Поэтому в Trunc передается что-то чуть большее, чем 201.
Вообще, в вашем случае лучше пользоваться не Trunc, а Round.
С функцией все в порядке. "Проблема" в особенностях представления вещественных чисел. Вероятнее всего тип Currency хранит представления результата 201 (то что получается в скобках) в виде 200.99(9). А Trunc не округляет, а именно отбрасывает дробную часть. Вот и результат 200*0.01=2.
Почитайте на досуге http://www.delphikingdom.com/asp/viewitem.asp?catalogid=374
Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter. Функция может не работать в некоторых версиях броузеров.