FormatFloat — Функция Delphi


Функции Delphi FormatFloat и Format

У меня есть приложение, в котором пользователи могут установить, как отображаются значения. Пользователи вводят строку форматирования, и компонент использует FormatFloat для отображения значения.

Но теперь мы используем новый сторонний компонент, который форматирует значения с использованием функции Format, и, конечно, ни один из наших пользовательских форматов не работает, поскольку функции Format и FormatFloat используют другой синтаксис.

Знает ли кто-нибудь о способе преобразования между этими двумя? Или, может быть, у кого-то есть код для этого?

Хотя строки формата для FormatFloat могут быть более или менее преобразованы в формат Format, вы можете получить реальное сходство для положительных значений. Метод Format просто не обеспечивает достаточной гибкости для использования функций и мелкозернистого управления, которые предлагают строки формата для метода FormatFloat.

Например, метод FormatFloat позволяет использовать три разных формата для положительных, отрицательных и нулевых значений. Кроме того, строки формата FormatFloat допускают строковые литералы, например. ‘#, ## 0,00;; Нулевой’; (это означает, что нулевые значения печатаются как «Zero» ).

Чтобы получить что-то подобное с помощью функции Format, вам самому нужно будет выполнить всю работу grunt, которую FormatFloat делает для вас через строку формата.

Итак, хотя я не против изменения сторонних источников управления, поскольку я против изменения источников vcl, я с Дэвидом на этом: найдите способ заставить сторонний элемент управления использовать функцию FormatFloat. Предпочтительно через пользовательский потомок или через класс интерполятора (также известный как класс перехватчика), но если это не удается, во что бы то ни стало, измените источник управления третьей стороной. Просто убедитесь, что вы правильно пометили измененные разделы, чтобы вы могли легко переделать его при переключении на новую версию этого элемента управления.

Справочник по компонентам Delphi. Часть 1
Страница 10. Функции преобразования чисел с плавающей точкой

Функции преобразования чисел с плавающей точкой

Преобразование числа с плавающей точкой (далее в этом разделе просто числа) в текстовую строку и обратно всегда было достаточно сложной задачей. Для ее решения в Delphi есть функции сразу трех уровней сложности.

Первый — самый простой — представлен функцией FloatToStr:

function FloatToStr ••-••-alue : Extended): string;

Число, заданное параметром Value, преобразуется в возвращаемую функцией строку. Формат преобразования соответствует типу преобразования g функции Format, причем длина выходной строки принимается равной 15 символам.

Больше возможностей для управления форматом вывода дает функция:

Здесь Value — преобразуемое значение, Format — один из предопре­деленных форматов. Хотя этот параметр имеет тип TFloatFormat, он имеет очень много общего с типами преобразований в функции Format (ссылки на них есть в предлагаемой таблице). Параметр Precision задает общее число символов в выходной строке и не должен превышать 7 для фактичес­кого параметра типа Single, 15 — для Double и 18 — для Extended. Digits — это параметр, интерпретируемый в зависимости от значения параметра Format:

Научный формат, соответствует типу е. Precision задает общее число символов, Digits — число знаков в показателе экспоненты <0-4).

Формат с фиксированной точкой; соответствует типу f. Precision задает общее число символов, Digits — число знаков после запятой (0-18). Если значение Precision мало для представления числа, используется научный формат.

Обобщенный формат, соответствует типу д (см. описание функции Format).

Отличается от fTFixed наличием символов-разделителей тысяч (см. тип преобразования п).

Соответствует типу преобразования т. Параметр Digits задает число символов после десятичной точки в выходной строке (0-18).

В случае, когда в функцию переданы значения Value, соответствующие особым случаям сопроцессора («не-число», плюс и минус бесконечность), она возвра­щает соответственно строки ‘NAN’, ‘INF’ и ‘-INF’.

Наконец, возможность полного управления форматом предоставляет функция FormatFloat:

Она преобразует число в строку в соответствии со спецификатором формата, содержащимся в параметре Format. Правила его задания следующие:

Поле для цифры. Если форматируемая величина имеет в этой позиции цифру, то вставляется она, в противном случае вставляется 0.

Поле для цифры. Если форматируемая величина имеет в этой позиции цифру, то вставляется она, в противном случае ничего не вставляется.

Поле для десятичной точки. Сюда вставляется символ, определенный константой DecimalSeparator.

Поле для разделителя тысяч. Оно означает, что группы по три цифры, считая влево от десятичной точки, будут разделяться специальным символом (он задан константой ThousandSeparator). Местоположение поля может быть произвольным.

Признаки представления числа в научном формате. Появление любого из этих аргументов означает, что число будет преобразовано с харак­теристикой и мантиссой. Вставка нулей после такого аргумента позволяет определить ширину мантиссы. Разница между Е+, е+ и Е-, е-в том, что в первых двух случаях ставится «+» при выводе положи­тельных чисел.

Символы, заключенные в обычные или двойные кавычки, напрямую включаются в выходную строку.

Разделяет спецификаторы формата для положительных, отрицательных и нулевых чисел.

1. Число всегда округляется до той точности, которую позволяет заданное программистом количество полей для размещения цифр (‘0’ и ‘#’).

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

3. Символ ‘;’ позволяет задать три разных формата вывода для чисел с разным знаком. При различном количестве форматов они применяются следующим образом:

Илон Маск рекомендует:  Что такое код xml_parse_into_struct

• один: применяется для всех чисел;

• два: первый применяется для чисел, больших или равных нулю, второй — для отрицательных;

• три: первьш применяется для положительных, второй — для отрицательных чисел, третий — для нуля.

Если форматы для отрицательных чисел или нуля пусты, применяется формат для положительных чисел.

Если пуст формат для положительных чисел или спецификатор формата вообще не задан (пустая строка), то числа форматируются согласно обобщенному формату (как в функции FloatToStr). Такое форматирование применяется также в случае, если число значащих цифр слева от десятичной точки превысило 18 и не задан научный формат.

Применение спецификатора иллюстрируется в таблице на примере преобразо­вания четырех чисел:

FormatFloat — Функция Delphi

Собственно интересует нет ли функции, которая помогла бы преобразовать дробное число в строку без всяких там добавок вроде экспоненты. А то когда у меня число заходит за рубеж 10+E18, любая дельфовая функция преобразования добавляет этот самый E18, а мне надо без него.
Может кто знает?

The Precision parameter specifies the precision of the given value. It should be 7 or less for values of type Single, 15 or less for values of type Double, and 18 or less for values of type Extended.

>этот самый E18, а мне надо без него

И что ты хотел бы видеть в младших разрядах чила, если информации о них нет? Нули? Тогда домножь на 10^n, затем FormatFloat и пририсуй n нулей.

Как «бывший» физик спрошу. А какой физический смысл может быть у числа представленного более чем 18 значащими разрядами?
Я, лично, значения представленные более чем 5 разрядов, вообще не рассматриваю. Кроме, конечно, констант.

Между 100 и 1E2 есть принципиальная разница — в первом случае погрешность не превышает 0.5, во втором — 50. То есть первое число — это представление чисел от 99.5 до 100.5, а второе — от 50 до 150.

>И что ты хотел бы видеть в младших разрядах чила, если информации о них >нет? Нули? Тогда домножь на 10^n, затем FormatFloat и пририсуй n нулей.

Так нет у меня там нулей. Числа там идут. Есль говорить предметно, то я пишу калькулятор, наподобии виндовского.
Дорустим, есть число 2 в степени 64. Так вот в виндовом калькуляторе оно отображается, как 18446744073709551616, а у меня 1,84467440737096Е19.

Вот, собственно, в чем проблема. Я хочу чтобы число отображалось полностью, а дельфовые функции конвертации не позволяют получить строку с числом, содержащую более 18 символов.

В дельфовых функциях используется такой код:
@@1: CMP EAX,18
JLE @@2
MOV EAX,18
@@2: MOV Precision,EAX

То есть, если выставлять точность выше 18, она все равно ее срежет.

Plotnick (24.11.05 10:10) [5]

Вещественные числа Delphi не могут хранить столь длинную мантиссу.

Sandman29 © (24.11.05 10:45) [7]
Вещественные числа Delphi не могут хранить столь длинную мантиссу.

Все вещественные(кроме real48) — стандарт IEEE, и Дельфи здесь ни при чем.

В данном случае

Пиши свой класс длинны чисел и свою математику для них, не используй стандартные математические выражения

Несовсем понял насчет собственной математики.
По Вашим словам, получается, что, фактически, Extended не хранит все число, а лишь ту часть, которая показана? А остальное, при надобности добивает нулями?
Но это не так. Я делаю простой пример, набиваю 2 в степени 64, число у меня отображается, как 184467440737095516Е19. То есть, начни я его делить на два 64 раза, я должен был бы не получить исходную величину. На самом деле все в порядке, исходня величина на месте. Значит переменная хранит значение так, как оно есть на самом деле. Поэтому математика собственная не нужна. Нужен лишь алгоритм перевода в строку.

Plotnick (24.11.05 12:09) [10]

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

184467440737095516Е19 такое число невозможно представить в Int64, это число близкое к 2^128

Extended 3.6 x 10^–4951 .. 1.1 x 10^4932 19–20
1. 19 для положительных чисел.

2. 2^63 = 18 446 744 073 709 551 616

3. Кода от автора пока не видать

4. Виндоуский калькулятор работает с 128 битными числами.

Очень интересует пункт 3


> Plotnick (24.11.05 12:09) [10]
> Нужен лишь алгоритм перевода в строку.

Мыслим логически.
1. Делим число на 10
2. берём остаток, умножаем на 10, округляем, преобразовываем кцелому, переводим в строку, прибавляем к результату.
3. отбрасываем у числа после деления дробную часть
4 гото 1

PS. Время набития кода 30 сек.


> Если на 2 умножить миллион раз, то число во всей компьютерной
> памяти не поместится. У Extended гораздо меньший размер
> и соответственно ограничение на количество значащих цифр.
> 2 в 64 степени не вписываются.

Чего-чего не вписывается? 1.1 x 10^4932 — мне кажется, что это значительно больше чем 2 в 64.


> 184467440737095516Е19 такое число невозможно представить
> в Int64, это число близкое к 2^128

В Dword64 возможно. Знаю, знаю — в дельфи такой тип не поддерживается. Но мне приходится как-то поддерживать.


> 3. Кода от автора пока не видать

Какого кода? Две кнопки — в одной X := X*2; В другой X := X/2. Код :)))

Вроде, как-то написал, но возникла проблема с функцией Int.

var
F1,F2: Extended;
Res: Extended;
IntRes: Integer;
Dig: String;
Pres: String;
InsertTo: Integer;
begin
F1 := F;
F2 := F;
if F1 10 do begin
F1 := Int(F1/10)*10;
Res := F2 — F1;
IntRes := Round(Int(Res));
Insert(IntToStr(IntRes),Dig,InsertTo);
F1 := F1/10;
F2 := F1;
end;
IntRes := Round(Int(F1));
Insert(IntToStr(IntRes),Dig,InsertTo);
F1 := F — Int(F);
Pres := FormatFloat(«.##########»,F1);
Result := Dig + Pres;

Илон Маск рекомендует:  Контейнеры тела документа нтмl body

Целую часть я преобразую сам. А для дробной решил воспользоваться конструкцией:

Десяти знаков после запятой мне хватает. Но вот беда — для числа вида:

конструкция F1 := F — Int(F); возвращает нуль. И число в итоге превращается в:

без дробной части.

Сорри по поводу:

запятую пропустил. 1,84467440737095516Е19

Опытным путем выяснил, что

Убираем один разряд, появляется дробная часть:

Короче, не хватает точности вычислений при больших числах.

Plotnick (24.11.05 13:32) [15]

> У Extended гораздо меньший размер
> и соответственно ограничение на количество значащих цифр.
> 2 в 64 степени не вписываются.


> Sandman29 © (24.11.05 16:31) [18]
> > У Extended гораздо меньший размер
> > и соответственно ограничение на количество значащих цифр.
> > 2 в 64 степени не вписываются.

Странно, у меня «вписываются»

FormatFloat

Format a float according to a certain mask.

Declaration

Source position: sysstrh.inc line 208

const Format : string ;


const Format : string ;

Description

FormatFloat formats the floating-point value given by Value using the format specifications in Format . The format specifier can give format specifications for positive, negative or zero values (separated by a semicolon).

If the formatspecifier is empty or the value needs more than 18 digits to be correctly represented, the result is formatted with a call to FloatToStrF with the ffGeneral format option.

The following format specifiers are supported:

0 is a digit place holder. If there is a corresponding digit in the value being formatted, then it replaces the 0. If not, the 0 is left as-is. # is also a digit place holder. If there is a corresponding digit in the value being formatted, then it replaces the #. If not, it is removed. by a space. . determines the location of the decimal point. Only the first ‘.’ character is taken into account. If the value contains digits after the decimal point, then it is replaced by the value of the DecimalSeparator character. , determines the use of the thousand separator character in the output string. If the format string contains one or more ‘,’ charactes, then thousand separators will be used. The ThousandSeparator character is used. E+ determines the use of scientific notation. If ‘E+’ or ‘E-‘ (or their lowercase counterparts) are present then scientific notation is used. The number of digits in the output string is determined by the number of 0 characters after the ‘ E+ ‘ ; This character separates sections for positive, negative, and zero numbers in the format string.

Errors

If an error occurs, an exception is raised.

See also

Convert a float value to a string using a fixed format.

Знаки после запятой.

04.05.2012, 15:56

Как ограничить количество знаков после запятой, не ограничивая количество до запятой?
Как ограничить количество знаков после запятой, не ограничивая количество до запятой? Если, к.

Цифры после запятой.
сейчас при помощи ffExponent в 1 и 2 едитах после запитой 5 цифр, как зделать так, если программа.

Цифры после запятой
Люди подскажите пожалуйста как убрать цифры после запятой, 461545,50391. Вот код моего приложения.

Цифры после запятой
нужно увеличить количество чисел после запятой он выдаёт 6 чисел, а остальные округляет и.

Контроль знаков после запятой
Добрый день. Возникла проблема. Требуется сделать так, что бы пользователь вводил в поле число и.

Delphi FormatFloat различное поведение (переменная & набор данных)

Я нашел странное поведение функции FormatFloat в Delphi. Позвольте мне показать пример.

значение, которое будет преобразовано: 129809,495
форматированный вывод желаемого: 129,809.50

Случай 1: Преобразование из строки

Случай 2: Преобразование из двойной переменной

Случай 3: Преобразование из поля набора данных

Я тестировал это поведение с использованием SQL Server 2008 & Firebird 1.5.
Компонент используется как компоненты ADO и компоненты UniDAC (по DevArt), и все они имеют одинаковое поведение.

Я пытался сделать это:

  • FormatFloat (», 0,00′ , Dataset.Field [0] .AsFloat);
  • ФорматFloat (‘, 0,00’, StrToFloat (Dataset.Field [0] .AsString));
  • val: = Dataset.Field [0] .AsFloat; FormatFloat (‘, 0.00’, val);
  • str: = Dataset.Field [0] .AsString; FormatFloat (‘, 0.00’, StrToFloat (str));
  • val: = StrToFloat (Dataset.Field [0] .AsString); FormatFloat (‘, 0.00’, val);

Но все это привело же неверного преобразования .49 вместо .50

1, совместимом является

Кто-нибудь есть решение для такого поведения? Потому что было бы слишком много работы, чтобы принудительно преобразовать StrToFloat, а затем переформатировать переменную/выход. И это обходное решение не может применяться к сторонним компонентам, которые использовали FormatFloat

Любая помощь была оценена. Благодаря

Создан 26 июл. 14 2014-07-26 03:54:17 saintfalcon

Delphi FormatFloat различное поведение (переменная & набор данных)

Я нашел странное поведение функции FormatFloat в Delphi. Позвольте мне показать пример.

значение, которое будет преобразовано: 129809,495
форматированный вывод желаемого: 129,809.50

Случай 1: Преобразование из строки

Случай 2: Преобразование из двойной переменной

Случай 3: Преобразование из поля набора данных

Я тестировал это поведение с использованием SQL Server 2008 & Firebird 1.5.
Компонент используется как компоненты ADO и компоненты UniDAC (по DevArt), и все они имеют одинаковое поведение.

Я пытался сделать это:

  • FormatFloat (», 0,00′ , Dataset.Field [0] .AsFloat);
  • ФорматFloat (‘, 0,00’, StrToFloat (Dataset.Field [0] .AsString));
  • val: = Dataset.Field [0] .AsFloat; FormatFloat (‘, 0.00’, val);
  • str: = Dataset.Field [0] .AsString; FormatFloat (‘, 0.00’, StrToFloat (str));
  • val: = StrToFloat (Dataset.Field [0] .AsString); FormatFloat (‘, 0.00’, val);

Но все это привело же неверного преобразования .49 вместо .50

1, совместимом является

Кто-нибудь есть решение для такого поведения? Потому что было бы слишком много работы, чтобы принудительно преобразовать StrToFloat, а затем переформатировать переменную/выход. И это обходное решение не может применяться к сторонним компонентам, которые использовали FormatFloat

Илон Маск рекомендует:  Проблемы безопасности cgi скриптов

Любая помощь была оценена. Благодаря

Создан 26 июл. 14 2014-07-26 03:54:17 saintfalcon

Функции Delphi FormatFloat и Format

У меня есть приложение, в котором пользователи могут настроить отображение значений. Пользователи вводят строку форматирования, а компонент использует FormatFloat для отображения значения.

Но теперь мы используем новый сторонний компонент, который форматирует значения с помощью функции Format, и, конечно, ни один из наших пользовательских форматов не работает, так как функции Format & FormatFloat используют другой синтаксис.

Так кто-нибудь знает способ преобразования между ними? Или, может быть, у кого-то есть код для этого?

2 ответа

Хотя строки формата для FormatFloat могут быть более или менее преобразованы в строки формата, вы можете получить реальное сходство только для положительных значений. Метод Format просто не обеспечивает достаточной гибкости для объединения функций и детального управления, которые предоставляют строки формата для метода FormatFloat.

Например, метод FormatFloat допускает три различных формата для положительных, отрицательных и нулевых значений. Кроме того, строки формата FormatFloat допускают строковые литералы, например, ‘#, ## 0.00 ;; Zero’; (что означает, что нулевые значения печатаются как «Ноль»).

Чтобы получить что-то похожее, используя функцию Format, вы сами должны выполнить всю тяжелую работу, которую FormatFloat выполняет для вас, через строку формата.

Таким образом, хотя я и выступаю против изменения источников сторонних элементов управления, так же как я против изменения исходных кодов vcl, я с Дэвидом в этом вопросе: найдите способ заставить сторонний элемент управления использовать функцию FormatFloat. Желательно через пользовательский потомок или через класс промежуточного устройства (также известный как класс перехватчика), но если это не удается, непременно измените источник стороннего элемента управления. Просто убедитесь, что вы пометили измененные разделы правильно, чтобы вы могли легко повторить их при переходе на новую версию этого элемента управления.

Округление чисел в Delphi

Округление чисел в построении программ очень важный механизм. Он позволяет управлять точностью получаемых вычислений, а так же влиять на ход выполнения алгоритма в процессе работы программы.

В программировании можно выделить несколько возможных вариантов округления – округление до целого или до заданной точности знаков после запятой. Так же оно различается по механизму округления – до ближайшего целого, в сторону большего целого или наименьшего целого значения. Для всех этих задач в Delphi используется набор математических функций, доступных после добавления в разделе описания соответствующей библиотеки:

Округление числа до целого значения

Для округления до целого числа используется следующий набор функций:

Ceil(X) — до целого в большую сторону;

Floor(X) — до целого в меньшую сторону;

Round(X) — число до целого в ближайшую сторону;

Trunc(X) — число до целого путем отбарасывания дробной части.

В качестве параметра эти функции используют дробное значение X и возвращают целое. Примеры округления чисел:

// до ближайшего большего целого:
A := Ceil(15.15); // A = 16
В := Ceil(15.95); // В = 16

// до ближайшего меньшего целого:
A := Floor(15.15); // A = 15
В := Floor(15.95); // В = 15

// по математическим правилам до ближайшего целого:
A := Round(15.15); // A = 15
B := Round(15.95); // B = 16
C := Round(15.5); // C = 16
D := Round(15.4999); // D = 15

// отбрасывание дробной части
A := Trunc(15.15); // A = 15
В := Trunc(15.95); // В = 15

* Несмотря на схожесть результата, Floor и Trunc имеют некоторое отличие. Floor возвращает значение типа Integer, тогда как Trunc — Int64, имеющий больший диапазон значений. Ceil так же возвращает значение Integer. Round возвращает Int64.

Округление до заданной точности знаков после запятой

Наиболее удобной функцией для этих вычислений является SimpleRoundTo. В качестве параметров ей нужно указать дробное число, а вторым параметром отрицательным целым числом. Второй параметр указывает на количество необходимых знаков после запятой.

A := SimpleRoundTo(15.1219, -1); // A = 15.1
B := SimpleRoundTo(15.1219, -2); // B = 15.12
C := SimpleRoundTo(15.1219, -3); // C = 15.122
D := SimpleRoundTo(15.1219, -4); // D = 15.1219
E := SimpleRoundTo(15.1219, -5); // E = 15.1219

Следует обратить внимание, что округление происходит по математическим правилам к ближайшему значению. Кроме того, если задать точность большую, чем в исходном значении, нули функция не подставит.

Другие механизмы округления чисел

Используя ту же функцию SimpleRoundTo можно так же выполнить округление до целого, указав вторым параметром ноль:

A := SimpleRoundTo(15.1219, 0); // A = 15

Если указывать положительные значения, то задается округление до нужной разрядности числа:

A := SimpleRoundTo(1235.1219, 1); // A = 1240 – до десятков
B := SimpleRoundTo(1235.1219, 2); // B = 1200 – до сотен
C := SimpleRoundTo(1235.1219, 3); // C = 1000 – до тысяч

Функция Frac(x) позволяет отбросить целое число, оставив только дробную часть:

Delphi FormatFloat другое поведение (переменная и набор данных)

Я обнаружил странное поведение функции FormatFloat в Delphi. Позвольте мне показать тематическое исследование.

значение для преобразования: 129809,495
желаемый форматированный вывод: 129 809,50

Случай 1: преобразование из строки

Случай 2: преобразование из двойной переменной

Случай 3: Преобразование из поля набора данных

Я тестировал это поведение с использованием SQL Server 2008 и Firebird 1.5.
Используемые компоненты — это ADO-компоненты и UniDAC-компоненты (от DevArt), и все они ведут себя одинаково.

Я пытался сделать это:

  • FormatFloat (‘, 0.00’, Dataset.Field [0].AsFloat);
  • FormatFloat (‘, 0,00’, StrToFloat (Dataset.Field [0].AsString));
  • val: = Dataset.Field [0].AsFloat; FormatFloat (‘, 0,00’, val);
  • str: = Dataset.Field [0].AsString; FormatFloat (‘, 0,00’, StrToFloat (str));
  • val: = StrToFloat (Dataset.Field [0].AsString); FormatFloat (‘, 0,00’, val);

Но все это привело к тому же неправильному преобразованию.49 вместо.50

1 способ, который работает

У кого-нибудь есть решение для такого поведения? Потому что было бы слишком много работы, чтобы принудительно преобразовать StrToFloat и затем переформатировать переменную / вывод. И этот обходной путь не может быть применен к сторонним компонентам, которые использовали FormatFloat

Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL