Как преобразовать число с плавающей запятой в строку с макс. 2 десятичных знака в Delphi - PullRequest
0 голосов
/ 04 июля 2018

Как я могу преобразовать число с плавающей запятой в строку с максимумом 2 десятичных цифр в Delphi7 ?

Я пытался использовать:

 FloatToStrF(Query.FieldByName('Quantity').AsFloat, ffGeneral, 18, 2, FS);

Но с учетом вышеизложенного иногда возвращается более 2 десятичных цифр, т.е. результат: 15,60000009

Ответы [ 3 ]

0 голосов
/ 06 июля 2018

Используйте ffFixed вместо ffGeneral.

ffGeneral игнорирует параметр Decimal.

Когда вы используете ffGeneral, 18 говорит, что вы хотите 18 значащих десятичных цифр. Затем процедура будет выражать это число самым коротким образом, используя при необходимости научную запись. 2 игнорируется.

Когда вы используете ffFixed, вы говорите, что хотите 2 цифр после десятичной точки.

Если вам интересно, почему вы иногда получаете значения, которые кажутся неточными, на этом сайте и в других материалах можно найти много полезного, объясняющего, как работают числа с плавающей запятой.

В этом случае AsFloat возвращает double, который, как и (большинство) других форматов с плавающей запятой, сохраняет свое значение в двоичном виде. Точно так же, как 1/3 нельзя записать в десятичном виде с конечными цифрами, так и 15,6 нельзя представить в двоичном виде в конечном числе битов. Система выбирает самое близкое возможное значение, которое может быть сохранено в double. Точное значение в десятичном виде:

15.5999999999999996447286321199499070644378662109375

Если бы вы запросили 16 цифр точности, значение было бы округлено до 15,6. Но вы попросили 18 цифр, так что вы получите 15.5999999999999996.

0 голосов
/ 07 июля 2018

Я использую эту функцию в моем приложении:

function sclCurrencyND(Const F: Currency; GlobalDegit: word = 2): Currency;
var R: Real; Fact: Currency;
begin
  Fact:= power(10, GlobalDegit);
  Result:= int(F*Fact)/Fact;
end;
0 голосов
/ 04 июля 2018

Если вы действительно имеете в виду то, что пишете (MAX 2 десятичных знака) и не означают ВСЕГДА 2 десятичных знака, тогда два фрагмента кода в комментариях не дадут вам того, о чем вы просили (они вернут строку, которая ВСЕГДА имеет две десятичные цифры, т. е. ONE возвращается как «1,00» (или «1,00» для формата в зависимости от вашей десятичной точки).

Если вы действительно хотите опцию с MAX 2 десятичных цифр, вам придется выполнить небольшую постобработку возвращаемой строки.

FUNCTION FloatToStrMaxDecimals(F : Extended ; MaxDecimals : BYTE) : STRING;
  BEGIN
    Result:=Format('%.'+IntToStr(MaxDecimals)+'f',[F]);
    WHILE Result[LENGTH(Result)]='0' DO DELETE(Result,LENGTH(Result),1);
    IF Result[LENGTH(Result)] IN ['.',','] THEN DELETE(Result,LENGTH(Result),1)
  END;

Альтернативная (и, возможно, более быстрая) реализация может быть:

FUNCTION FloatToStrMaxDecimals(F : Extended ; MaxDecimals : BYTE) : STRING;
  BEGIN
    Result:=Format('%.'+IntToStr(MaxDecimals)+'f',[F]);
    WHILE Result[LENGTH(Result)]='0' DO SetLength(Result,PRED(LENGTH(Result)));
    IF Result[LENGTH(Result)] IN ['.',','] THEN SetLength(Result,PRED(LENGTH(Result)))
  END;

Эта функция будет возвращать число с плавающей запятой с MAX числом указанных десятичных цифр, т.е. одна половина с цифрами MAX 2 вернет «0.5», а треть с десятичными цифрами MAX 2 вернет «0.33», а две трети с десятичными цифрами MAX 2 вернет «0.67». ДЕСЯТЬ с МАКС. 2 десятичных знака вернет "10".

Последний оператор IF должен действительно проверять правильную десятичную точку, но я не думаю, что возможны какие-либо значения, кроме точки или запятой, и если одно из них останется последним символом в строке после удаления всех нули с конца, тогда он ДОЛЖЕН быть десятичной точкой.

Также обратите внимание, что этот код предполагает, что строки индексируются с 1 для первого символа, как это всегда происходит в Delphi 7. Если вам нужен этот код для мобильных компиляторов в новых версиях Delphi, вам необходимо обновить код. Я оставлю это упражнение читателю: -).

...