Single — Тип Delphi


Точность Single

30.01.2014, 13:20

Точность числа
как в делфи определить точность числа? Например, 1.22222 с тоностью 0.001=1.222 с точностью 1=1

точность вычислений и быстродействие
Добрый день! В моей программе производится много вычислений с числами в формате extended. Их.

Глюки VB — точность вычислений (Single, Double)
Знатоки VB, подскажите, пожалуйста. Периодически возникает проблема когда работаешь со переменными.

Single — Тип Delphi

ДОБРОГО ВРЕМЕНИ СУТОК.

Есть данные 8-байт. Все 4 переменные типа word содержат в себе одно значение с плавающей точкой; (4byte*2=8byte)
Я знаю что формат этих данных float или real.

Как присвоить их одной переменной это понятно
допустим b4 самое старшее слово(2 байта).

b4*$ffffff+b3*$ffff+b2*$ff+b1=8 байт данных в формате LongWord

Ув. мастера вопрос:

Как перевести эти 8 бит данных в формат float или real но с плавающей запятой?
Есть догадки что через указатели.


> vodvorezlaya

Воспользуйся типом Extended

в delfi приведение типов делается так
:= ВоЧтоПривести(Переменная);

Самый маленький тип с плавточкой Single занимает 4 байта т.е. в твои 8 байт можно запихнуть 2 переменные Single.

1:
var
pw: array[0..3]of word;
_pf_pw: array[0..1]of single absolute pw;
_pd_pw: array[0..0]of double absolute pw;
2:
type
TExplicitCastFloat = packed record
case byte of
0: (pw: array[0..3]of word);
1: (pf: array[0..1]of single);
2: (pd: array[0..0]of double);
end;
3:
pf[0]:= single((@pw[0])^);
4:
move(pw[0], pf[0], sizeof(pf[0]));

Я нишута не понял.

приведи реальное содержимое того что имеется и того что должно получиться в результате

Поддерживаю Сергей М. © (01.09.06 16:48) [4]

В Delphi нет типа float, есть single (4 байта). Типы real и double эквивалентны. Занимают 8 байт.

Если тебе надо «переконвертировать» double в single, то делает ся Очень Просто:

var
d : double;
s : single;
begin
d := 18.144; // 8 байт
s := d; // 18.144; 4 байта
.
end;

Что касается массива (например ARR = array[0..3] of word ), то преобразовать в double можно так:

d := double(ARR); // лично я сталкивался с ошибками
или
d := pdouble(@ARR[0])^;

НО самый крутой способ, как предложил han_malign © :

var
ARR = array[0..3] of word;
d: double absolute ARR;

В таком случае ARR и d будут указывать на одну и туже область памяти. Можешь обращаться к массиву, а можешь сразу к double переменной


> Хрень какая-то .
>
> Я нишута не понял.
>
> приведи реальное содержимое того что имеется и того что
> должно получиться в результате

Народ. Вопрос не в том немного.

В шестнадцатеричных кодах нет знака запятой, она содержится в первых розрядах типа данных Real. Тоесть если присвоить переменной типа Real переменную LongWord то получится тоже значение, но без знаков после запятой, а они там есть. Оно попросту не воспримет тип LongWord как имеющий знаки после запятой.
Т.е. нужно чтоб оно поняло что этот тип нужно воспринимать как Float.


> 1:
> var
> pw: array[0..3]of word;
> _pf_pw: array[0..1]of single absolute pw;
> _pd_pw: array[0..0]of double absolute pw;
> 2:
> type
> TExplicitCastFloat = packed record
> case byte of
> 0: (pw: array[0..3]of word);
> 1: (pf: array[0..1]of single);
> 2: (pd: array[0..0]of double);
> end;
> 3:
> pf[0]:= single((@pw[0])^);
> 4:
> move(pw[0], pf[0], sizeof(pf[0]));

Я понял, ты шаришь. А можна с небольшим комментарием.
Спасибо.


> 1:
> var
> pw: array[0..3]of word;

А где младший и где старший розряды?


> В шестнадцатеричных кодах нет знака запятой, она содержится
> в первых розрядах типа данных Real

type
PExtended = ^Extended;
..

var
MyArray: array[0..3] of Word;
MyFloatValue: Extended;
..
MyFloatValue := PExtended(@MyArray)^;

> переменные типа word содержат в себе одно значение с плавающей точкой
Тип Word не может содержать дробные числа.
Машинное представление дробных чисел базируется на мантиссе, порядке и основании. Ищи эти слова в гугле.


> Я понял, ты шаришь. А можна с небольшим комментарием.
> А где младший и где старший розряды?

— а вот это уже зависит от способа кодирования битового потока, big-endian(встречается, так же, как — network order, для значений выровненных на размер октета), или little-endian(«обычное» представление для семейства x86 процессоров). В случае little-endian, если данные выровненны на размер октета — никаких дополнительных действий для разбора потока делать не надо — достаточно прямого приведения.
Что находится в самом битовом потоке — целиком и полностью на совести разработчика — если известно, что это стандартный double — нам не важно где у него мантисса, а где знак, нам важно заполнить 64-бита переменной типа double — 64-мя битами из потока, в соответсвии с правилами кодирования битового потока.
Выше, я, как раз, привел четыре способа прямого отбражения little-endian значений на разные типы данных.


> 1:
> var
> pw: array[0..3]of word;
> _pf_pw: array[0..1]of single absolute pw;
> _pd_pw: array[0..0]of double absolute pw;

А эти способы разные?

Потому что первый не сработал.

han_malign какую литературу ты читал?

Там у меня вообще передача с контроллера Siemens Simatic S5 там какой то свой формат.

Как попробовать разными способами кодирования big-endian и little-endian.
> Ерунда какая-то)

Слушай han_malign, он шарит?


> vodvorezlaya (04.09.06 12:38) [12]


> Слушай han_malign, он шарит?


> передача с контроллера Siemens Simatic S5

А ты что не знаеш протокола передачи? Ты используеш OPC сервер?


> А ты что не знаеш протокола передачи? Ты используеш OPC
> сервер?

Нет, я написал сам модуль который по ком порту (через токовый преобразователь) передаёт данные к S5, могу код привести
:)
А что такое ОРС сервер?
Там что, дрова на Симатик есть?


> vodvorezlaya

Для работы с контроллерами я всегда использую OPC сервер. Как правило с ним поставляется диск с дровами и OPC сервером, через который моя прога коннектиттся к устройству.Это программа-прослойка. Этот сервер сам преобразует данные получаемые с контроллера по нужному протоколу. я правда не знаю поставляет ли Сиеменс такие веши. Wago, ICPCon и подобные поставляют. ИМХО Самому писать протоколы (тем более к Семену) геморрой.

http://www.runmode.com/usefulstuff.html
:
Notes on Simatic data storage
* Whenever you need to read or store values on Siemens PLCs, you must be aware that SIMATIC systems adopted the Big Endian byte order, see a brief description here: http://www.cs.umass.edu/

verts/cs32/endian.html
там же ссылки на протокол:
http://www.runmode.com/usefulstuff_files/AS511protocol_description.pdf
http://www.runmode.com/usefulstuff_files/0141_as511_komponente.zip

компонент правда на немецком, но это мелочи.


> ИМХО Самому писать протоколы (тем более к Семену) геморрой.

2 дня заняло написание полноценного модуля (не драйвера)


> http://www.runmode.com/usefulstuff.html
> :
> Notes on Simatic data storage
> * Whenever you need to read or store values on Siemens
> PLCs, you must be aware that SIMATIC systems adopted the
> Big Endian byte order, see a brief description here: http:
> //www.cs.umass.edu/

verts/cs32/endian.html
> там же ссылки на протокол:
> http://www.runmode.com/usefulstuff_files/AS511protocol_description.
> pdf
> http://www.runmode.com/usefulstuff_files/0141_as511_komponente.
> zip

У меня там другой протокол, но похоже
у меня RK-512


> 2 дня заняло написание полноценного модуля

Будь у тебя нормальный OPC ты бы такими вопросами не задавался

Слушай,
> Elen

как решить проблему := inttostr(Edit1.Text); не проходит, ошибку какую — то лепис


> := inttostr(Edit1.Text); не проходит, ошибку какую — то
> лепис

Начали за здравие, закончили заупокой)


> vodvorezlaya

А ты когда нибудь контроллерами занимался или новичок в этом деле?
(заодно Делфи подучи inttostr(Edit1.Text) это уже перегрев на работе)


> У меня там другой протокол, но похоже у меня RK-512

— да по барабану какой протокол, кодирование потока редко менятся. Но тут есть два варианта, либо они целиком 8 байт double переворачивают, либо пословно(из описания непонятно).
function ntod(pw: PWord; fFullSwap: boolean): double;
var __pw: array[0..sizeof(Result)div 2 — 1]of word absolute Result;
i: integer;
begin
if(fFullSwap)then begin
for i:= Low(__pw) to High(__pw) do begin
__pw[High(__pw)-i]:= Swap(pw^);
inc(pw);
end;
end else begin
for i:= Low(__pw) to High(__pw) do begin
__pw[i]:= Swap(pw^);
inc(pw);
end;
end;
end;
— но это если предполагать что там гарантированно стандартный double.


> это уже перегрев на работе

Так и есть.

> А ты когда нибудь контроллерами занимался или новичок в
> этом деле?

Каждый день симатик глаза мозолит, немного шарю в Step7.


> vodvorezlaya

Сочувствую. Мне с ICPcon попроще. и стоит он дешевле

Single — Тип Delphi

Порядковые типы
Из простых типов данных порядковые — самые простые. В этих типах информация представляется в виде отдельных элементов. Связь между отдельными элементами и их представлением в памяти определяет естественные отношения порядка между этими элементами. Отсюда и название порядковые.
В Object Pascal определены три группы порядковых типов и два типа, определяемых пользователем. Группы — это целые, символьные и булевы типы. Порядковые типы, задаваемые пользователем, — это перечисления и поддиапазоны.
Все значения любого порядкового типа образуют упорядоченную последовательность, и значение переменной порядкового типа определяется его местом в этой последовательности. За исключением переменных целых типов, значения которых могут быть как положительными, так и отрицательными, первый элемент любого порядкового типа имеет номер 0, второй элемент — номер 1 и т.д. Порядковый номер целого значения равен самому значению. Отношение порядка определяет общие для данных всех порядковых типов операции. Некоторые стандартные функции такого вида встроены в Object Pascal. Они представлены в табл. 1.1.

Для всех порядковых типов в Object Pascal существует операция задания типа для преобразования целых значений в значения соответствующих порядковых типов. Если Т — имя порядкового типа, а Х — целое выражение, то Т (X) воз-вращает значение Т с порядковым номером X.

Совет: Программисты, работающие на С и C++, для приращения или уменьшения значений переменных привыкли заметку использовать операторы «++» и «—«, возвращающие следующее и предыдущее значения. Программисты Delphi всегда разбивают эти операции на более простые составляющие с помощью функций Pred, Succ. Dec и Inc.


    Таблица 1.1. Операции над порядковыми типами

ОперацияОписание
Low (T)Минимальное значение порядкового типа Т
High(T)Максимальное значение порядкового типа Т
Ord(X)Порядковый номер значения выражения порядкового типа. Для целого выражения — просто его значение. Для остальных порядковых типов Ord возвращает физическое представление результата выражения, трактуемое как целое число. Возвращаемое значение всегда принадлежит одному из целых типов
Pred(X)Предыдущее по порядку значение. Для целых выражений эквивалентно Х-1
Succ(X)Следующее по порядку значение. Для целых выражений эквивалентно Х+1
Dec(V)Уменьшает значение переменной на 1. Эквивалентно V := Pred(V)
Inc(V)Увеличивает значение переменной на 1. Эквивалентно V := Succ(V)

Целые типы
В переменных целых типов информация представляется в виде целых чисел, т.е. чисел не имеющих дробной части. Определенные в Object Pascal целые типы подразделяются на физические (фундаментальные) и логические (общие). При программировании удобнее использовать логические целые типы, которые задают объем переменных в зависимости от типа микропроцессора и операционной среды таким образом, чтобы достигалась максимальная эффективность. Физические целые типы следует применять лишь в тех случаях, когда в первую очередь важны именно диапазон значений и физический объем переменной. В Object Pascal определены следующие целые типы.

    Integer
    Shortint
    Smallint
    Longint
    Byte
    Word
    Cardinal

Обратите внимание, что один из этих целых типов назван именно целым (integer). Это может иногда приводить к путанице, но мы легко сможем ее избежать, применяя термин целый к. группе типов, a integer — к конкретному типу, определяемому в программе этим ключевым словом. Переменные физических целых типов имеют разные диапазоны значений в зависимости от того, сколько байтов памяти они занимают (что равно значению, возвращаемому функцией SizeOf для данного типа). Диапазоны значений для всех физических типов перечислены в табл. 1.2.

    Таблица 1.2. Физические целые типы


    ТипДиапазон значенииФизический формат
    Shortint-128-1278 бит, со знаком
    Smallint-32 768-32 76716 бит, со знаком
    Longint-2 147 483 648-2 147 483 64732 бит, со знаком
    Byte0-2558 бит, без знака
    Word0-65 53516 бит, без знака


Диапазоны значений и форматы физических целых типов не зависят от микропроцессора и операционной системы, в которых выполняется программа. Они не меняются (или, по крайней мере, не должны меняться) с изменением реализации или версии Object Pascal.
Диапазоны значений логических целых типов (Integer и Cardinal) определяются совершенно иным образом. Как видно из табл. 1.3, они никак не связаны с диапазонами соответствующих физических типов. Обратите внимание, что в Delphi по умолчанию задано 32-разрядное представление.

Таблица 1.3. Логические целые типы


    ТипДиапазон значенийФизический формат
    Integer-32 768-32 76716 бит, со знаком (SmalIInt)
    Integer-2 147 483 648-2 147 483 64732 бит, со знаком (Longint)
    Cardinal0-65 53516 бит, без знака (Word)
    Cardinal0-2 14748364732 бит, без знака (Longint)

Совет: В С и C++ для целых значений определены типы int, short int (или просто short) и long int (или просто long). Тип int из C/C++ соответствует типу Integer из Delphi, a long из C/C++ — Longint из Delphi. Однако Shortint из C/C++ соответствует в Delphi не Shortint, a Smalltlnt. Эквивалент Shortint из Delphi в C/C++— это signed char. Тип unsigned char в C/C++ соответствует типу Byte из Delphi. В C/C++ существует еще тип unsigned long, аналога которому в Delphi нет.

Над целыми данными выполняются все операции, определенные для порядковых типов, но с ними все же удобнее работать как с числами, а не с «нечисленными порядковыми типами». Как и «живые» числа, данные целых типов можно складывать (+), вычитать (-) и умножать (*). Однако некоторые операции и функции, применяемые к данным целых типов, имеют несколько иной смысл.

Операция Результат
Abs (X) Возвращает абсолютное целое значение Х
Х Div Y Возвращает целую часть частного деления Х на Y
Х Mod Y Возвращает остаток частного деления Х на Y
Odd (X) Возвращает булево True (истина), если Х — нечетное целое, и False (ложь) — в противном случае
Sqr (X) Возвращает целый квадрат Х (т.е. Х*Х)

Символьные типы
Смысл символьных данных очевиден, когда они выводятся на экран или принтер. Тем не менее, определение символьного типа может зависеть от того, что подразумевать под словом символ. Обычно символьные типы данных задают схему взаимодействия между участками памяти разного объема и некоторым стандартным методом кодирования/декодирования для обмена символьной информацией. В классическом языке Pascal не задано никакой схемы, и в конкретных реализациях применялось то, что на том же компьютере мог использовать каждый.
В реализациях языка Pascal для первых микропроцессоров была применена 7-битовая схема, названная ASCII (American Standard Code for Information Interchange — Американский стандартный код для обмена информацией). Эта схема и поныне широко распространена, но информация хранится, как правило, в 8-битовых участках памяти. Дополнительный бит удваивает число возможных представлений символов, но реализации расширенного набора символов ASCII часто бывают далеки от стандарта. В данной версии Delphi определен набор 8-битовых символов, известный как расширенный (extended) ANSI (American National Standards Institute — Американский национальный институт стандартов). Как бы то ни было, символьную схему приходится воспринимать так, как ее воспринимает операционная система. Для оконных операционных систем фирмы Microsoft это схема ANSI, включающая ограниченное число предназначенных для вывода международных знаков. В стремлении же применить более обширный набор международных знаков весь компьютерный мир переходит к 16-битовой схеме, именуемой UNICODE, в которой первые 256 знаков совпадают с символами, определенными в схеме ANSI.
Для совместимости со всеми этими представлениями в Object Pascal определены два физических символьных типа и один логический.
Физические типы перечислены ниже.

AnsiChar Однобайтовые символы, упорядоченные в соответствии с расширенным набором символов ANSI
WideChar Символы объемом в слово, упорядоченные в соответствии с международным набором символов UNICODE. Первые 256 символов совпадают с символами ANSI


Символьные типы объемом в двойное слово (32 бит) отсутствуют.
Логический символьный тип именуется char. В классическом языке Pascal char— единственный символьный тип. В Delphi char всегда соответствует физическому типу данных AnsiChar. У американских программистов ассоциация символа с однобайтовой ячейкой памяти укоренилась за долгие годы настолько, что им зачастую просто не приходит в голову, что можно использовать другие схемы кодирования. Однако дискуссии по интернационализации программ в Internet и World Wide Web могут существенно изменить их отношение к проблеме объема символьных данных. Применяя логический тип char, следует делать реализации для других микропроцессоров и операционных систем, в которых char может определяться как WideChar. При написании программ, которые могут обрабатывать строки любого размера, для указания этого размера рекомендуется применять функцию SizeOf, не задавая ее жестко постоянной. Функция Ord (С), где С — любая переменная символьного типа, возвращает целое значение, которым символ С представлен в памяти.


    Chr (X)Преобразует целую переменную в переменную типа char с тем же порядковым номером. В Delphi это эквивалентно заданию типа Char (X)
    UpCaseПреобразует строчную букву в прописную

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


Совет: Процессор не различает типы char, определенные в C/C++ и Delphi. Однако функционально каждый из этих языков трактует данный тип совершенно по-разному. В C/C++ это целый тип, переменной которого можно присваивать целые значения. Переменной int можно присвоить символьное значение, а переменной char — целое. В Delphi символьные типы жестко отделены от численных. Для присвоения численному значению символьного здесь необходимо воспользоваться функцией Ord. В языке Basic один символ представляется так же, как и строка символов. Функция Chr из Delphi эквивалентна функции CHR$ из Basic. Функция Ord из Delphi, возвращающая код ANSI символьной переменной, подобна функции A3 С из Basic, аргумент которой представляет односимвольную строку.

Булевы типы
На ранней стадии обучения программисты осваивают понятие бита, два состояния которого можно использовать для записи информации о чем-либо, представляющем собой одно из двух. Бит может обозначать 0 или 1, ДА или НЕТ, ВКЛЮЧЕНО или ВЫКЛЮЧЕНО, ВЕРХ или НИЗ, СТОЯТЬ или ИДТИ. В Object Pascal информация о чем-либо, что можно представить как ИСТИНА (True) или ЛОЖЬ (False), хранится в переменных булевых типов. Всего таких типов че-тыре, и они представлены в табл. 1.4.


    Таблица 1.4. Размеры переменных булевых типов


    ТипРазмер
    Boolean1 байт
    ByteBool1 байт
    WordBool2 байт (объем Word)
    LongBool4 байт (объем Longint)


По аналогии с целыми и символьными типами, подразделяющимися на физические и логические, естественно предположить, что ByteBool, WordBool и LongBool — физические типы, Boolean — логический. Но в данном случае это не совсем так. Все четыре типа различны. Для Object Pascal предпочтителен тип Boolean, остальные определены для совместимости с другими языками программирования и операционными системами.
Переменным типа Boolean можно присваивать только значения True (истина) и False (ложь). Переменные ByteBool, WordBool и LongBool могут принимать и другие порядковые значения, интерпретируемые обычно как False в случае нуля и True — при любом ненулевом значении.

Совет: Булевы типы в Delphi можно сравнить с типом LOGICAL языка FORTRAN. В Basic, С и C++ булевы типы как таковые отсутствуют. Булевы выражения в этих языках применяются точно так же, как во всех остальных, однако результаты этих выражений интерпретируются не как значения отдельного типа, а как целые числа. Как в Basic, так и в C/C++ булевы выражения дают численные результаты, интерпретируемые как False в случае 0 и True — в случае любого ненулевого значения. Это совместимо с порядковыми значениями булевых выражений в Delphi. В C/C++ простые сравнения дают результат 1 (True) или 0 (False). Это эквивалентно булевым значениям Delphi. Только результат сравнения в Delphi выводится как булевый, а не целый. В большинстве случаев типу Boolean из Delphi соответствует тип char в C/C++. В Basic зарезервированы слова TRUE (эквивалентно константе -1) и FALSE (эквивалентно константе 0). В Basic TRUE меньше FALSE, в Delphi, наоборот, False меньше True.

Перечислимые типы
Type enum type = (first value, value2, value3, last value);
Обычно данные перечислимых типов содержат дискретные значения, представляемые не числами, а именами. Тип Boolean— простейший перечислимый тип в Object Pascal. Булевы переменные могут принимать два значения, выражаемые именами True и False, а сам тип определен в Object Pascal так, как будто он объявлен следующим образом:
Type Boolean = (False, True);
С помощью типа Boolean в Object Pascal выполняются сравнения, большинство же перечислимых типов — это просто списки уникальных имен или идентификаторов, зарезервированных с конкретной целью. Например, можно создать тип MyColor (мой цвет) со значениями myRed, myGreen и myBlue (мой красный, мой зеленый, мой синий). Это делается совсем просто:
Type MyColor = (myRed, myGreen, myBlue);
В этой строке объявлены четыре новых идентификатора: MyColor, myRed, myGreen и myBlue. идентификатором MyColor обозначен порядковый тип, следовательно, в синтаксисе Object Pascal можно применять этот идентификатор везде, где разрешены перечислимые типы. Остальные три идентификатора— это значения типа MyColor. Подобно символьным и булевым типам перечислимые не являются числами, и использовать их наподобие чисел не имеет смысла. Однако перечислимые типы относятся к порядковым, так что значения любого такого типа упорядочены. Идентификаторам в списке присваиваются в качестве порядковых номеров последовательные числа. Первому имени присваивается порядковый номер 0, второму — 1 и т.д.

Совет: В С и C++ есть тип enema, аналогичный перечислимому типу Delphi. Но в этих языках можно произвольно присваивать идентификаторам постоянные значения. В Delphi же соответствие имен и их значений фиксиро-вано: первому имени присваивается значение 0, каждому последующему — на единицу больше. В С тип enum применяется лишь как средство быстрого определения набора целых постоянных. В C++ объявленные в перечислимом типе идентификаторы можно присваивать только переменным того же типа.

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

Type subrange type = low value. high value;

Поддиапазонные переменные сохраняют все особенности исходного типа. Единственное отличие состоит в том, что переменной поддиапазонного типа можно присваивать только значения, входящие в заданный поддиапазон. Контроль за соблюдением этого условия задается командой проверки диапазона (range checking).
Необходимость явно определять поддиапазонный тип возникает нечасто, но все программисты неявно применяют эту конструкцию при определении массивов. Именно в форме поддиапазонной конструкции задается схема нумерации элементов массива.

Single — Тип Delphi

3.2.2. Вещественные типы Delphi

В Delphi существует четыре вещественных типа: Single , Double , Extended и Real . Их общий формат одинаков (рис. 3.1, а).

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

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

а) общий вид вещественного числа

б) Двоичное представление числа типа Single

Рис. 3.1. Хранение вещественного числа в памяти

Микропроцессор Intel 8086/88 и его улучшенные варианты — 80286 и 80386 — также не имели аппаратной поддержки вещественных чисел. Но у систем на базе этих процессоров была возможность подключения так называемого сопроцессора. Эта микросхема работала с памятью через шины основного процессора и обеспечивала аппаратную поддержку вещественных чисел. В системах средней руки гнездо сопроцессора обычно было пустым, т.к. это уменьшало цену (разумеется, вставить туда сопроцессор не было проблемой). Для каждого центрального процессора выпускались свои сопроцессоры, маркировавшиеся Intel 8087, 80287 и 80387 соответственно. Были даже сопроцессоры, выпускаемые другими фирмами. Они работали быстрее, чем сопроцессоры Intel, но появлялись на рынке позже. Тип вещественных чисел, поддерживаемый сопроцессорами, не совпадает с Real . Он определяется стандартом IEEE (Institute of Electrical and Electronics Engineers).

Чтобы обеспечить в своих системах поддержку типов IEEE, Borland вводит в Turbo Pascal типы Single , Double и Extended . Extended — это основной для сопроцессора тип, a Single и Double получаются из него очень простым усечением. Система команд сопроцессора допускает работу с этими типами: при загрузке числа типа Single или Double во внутренний регистр сопроцессора последний конвертирует их в Extended . Напротив, при выгрузке чисел этих типов из регистра в память сопроцессор усекает их до нужного размера. Внутренние же операции всегда выполняются с данными типа Extended (впрочем, из этого правила есть исключение, на котором мы остановимся позже, после детального рассмотрения формата различных типов). Single и Double позволяют экономить память. Ни один из них также не совпадает с типом Real . В системах с сопроцессорами новые типы обрабатываются заметно (в 2–3 раза) быстрее, чем Real (это с учетом того, что тип Real после соответствующего преобразования также обрабатывался сопроцессором; если же сравнивать обработку типа Extended на машине с сопроцессором и Real на машине без сопроцессора, то там на отдельных операциях достигалась разница в скорости примерно в 100 раз). Чтобы программы с этими типами можно было выполнять и в системах без сопроцессора, была предусмотрена возможность подключать к ним программный эмулятор сопроцессора. Обработка этих типов эмулятором была медленнее, чем обработка Real .

Начиная с 486-й серии Intel берет курс на интеграцию процессора и сопроцессора в одной микросхеме. Процент брака в микросхемах слишком велик, поэтому Intel идет на хитрость: если у микросхемы брак только в сопроцессорной части, то на этом кристалле прожигаются перемычки, блокирующие сопроцессор, и микросхема продается как процессор 80486SX, не имеющий встроенного сопроцессора (в отличие от полноценной версии, которую назвали 80486DX). Бывали и обратные ситуации, когда сопроцессор повреждений не имел, зато процессор был неработоспособен. Такие микросхемы превращали в «сопроцессор 80487». Но это уже из области экзотики, и, по имеющейся у нас информации, до России такой сопроцессор не дошел.

Процессор Pentium во всех своих вариантах имел встроенный блок вычислений с плавающей точкой (FPU — Floating Point Unit), и отдельный сопроцессор ему не требовался. Таким образом, с приходом этого процессора тип Real остался только для обратной совместимости, а на передний план вышли типы Single , Double и Extended . Начиная с Delphi 4, тип Real становится синонимом типа Double , а старый 6-байтный тип получает название Real48 .

Здесь и далее под словом Real мы будем понимать старый 6-байтный тип.

Существует директива компилятора <$REALCOMPATIBILITY ON/OFF>, при включении которой (по умолчанию она отключена) Real становится синонимом Real48 , а не Double .

Размеры полей для различных вещественных типов указаны в табл. 3.1.

Таблица 3.1. Размеры полей в вещественных типах

Тип Размер типа, байты Размер мантиссы, биты Размер экспоненты, биты
Single 4 23 8
Double 8 52 11
Extended 10 64 15
Real 6 40 7

Другие параметры вещественных типов, такие как диапазон и точность, можно найти в справке Delphi.

3.2.3. Внутренний формат вещественных чисел

Рассмотрим тип Single , т.к. он самый короткий и, следовательно, самый простой для понимания. Остальные типы отличаются от него только количественно. В дальнейшем числа в формате Single мы будем записывать как s eeeeeeee mmmmmmmmmmmmmmmmmmmmmmm, где s означает знаковый бит, е — бит экспоненты, m — бит мантиссы. Порядок хранения битов в типе Single показан на рис. 3.1, б (по принятым в процессорах Intel правилам байты в многобайтных значениях переставляются так. что младший байт идет первым, а старший — последним, и вещественных чисел это тоже касается В мантиссе хранится двоичное число. Чтобы получить истинное значение мантиссы, к ней надо мысленно добавить слева единицу с точкой (т.е., например, мантисса 1010000000000000000000 означает двоичную дробь 1.101). Таким образом, имея 23 двоичных разряда, мы записываем числа с точностью до 24-х двоичных разрядов.

Экспонента — по определению всегда целое число. Но способ записи экспоненты в вещественных числах не совпадает с рассмотренным ранее способом записи чисел со знаком. Ноль в этом представлении записывается как 01111111 (в обычном представлении это равно 127). Соответственно. 10000000 (128 в обычном представлении) означает единицу, а 01111110 (126) означает -1, и т. д. (т.е. из обычного беззнакового числа надо вычесть 127, и получится число, закодированное в экспоненте). Такая запись чиста называется нормализованной .

Из описанных правил есть исключения. Так, если все биты экспоненты равны нулю (т.е. там стоит число -127), то к мантиссе перед ее началом надо добавлять не «1.», а «0.» (денормализованная запись) . Это позволяет увеличить диапазон вещественных чисел. Если бы этого исключения не было, то минимально возможное положительное число типа Single было бы равно примерно 5,9·10 -39 . А так появляется возможность использовать числа до 1,4·10 -45 . Побочным эффектом этого является то, что числа, меньшие чем 1,17·10 -38 , представляются с меньшей, чем 24 двоичных разряда, точностью. Если все биты в экспоненте равны единице, а в мантиссе — нулю, то мы получаем комбинацию, известную как INF (от англ. Infinity — бесконечность). Эта комбинация используется тогда, когда результат вычислений превышает максимально допустимое форматом число. В зависимости от значения бита s бесконечность может быть положительной или отрицательной. Если же при такой экспоненте в мантиссе хоть один бит не равен нулю, такая комбинация называется NAN (Not A Number — не число). Попытки работы с комбинациями NAN или INF приводят к ошибке времени выполнения.

Для задания нуля все биты мантиссы и экспоненты должны быть равны нулю (формально это означает 0·10 -127 ). С учетом описанных правил, если хотя бы один бит экспоненты не будет равен нулю (т.е. экспонента будет больше -127), запись будет считаться нормализованной, и нулевая мантисса будет рассматриваться как единица. Поэтому никакие другие комбинации значений мантиссы и экспоненты не могут дать ноль.

А.Б. Григорьев: О чём не пишут в книгах по Delphi 1
Введение 1
Глава 1: Windows API и Delphi 2
1.1. Основы работы Windows API в VCL-приложениях 2
1.1.1. Что такое Windows API 2
1.1.2. Как получить справку по функциям Windows API 2
1.1.3. Дескрипторы вместо классов 5
1.1.4. Формы VCL и окна Windows 5
1.1.5. Функции обратного вызова 7
1.1.6. Сообщения Windows 8
1.1.7. Создание окон средствами VCL 10
1.1.8. Обработка сообщений с помощью VCL 11
1.1.9. Сообщения, определяемые пользователем 16
1.1.10. Особые сообщения 17
1.1.11. Графика в Windows API 17
1.1.12. ANSI и Unicode 20
1.1.13. Строки в Windows API 20
1.2. Примеры использования Windows API 22
1.2.1. Пример EnumWnd 22
1.2.2. Пример Line 23
1.2.3. Пример CoordLabel 25
1.2.4. Пример PanelMsg 26
1.2.5. Пример NumBroadcast 27
1.2.6. Пример ButtonDel 28
1.2.7. Пример GDIDraw 28
1.2.8. Пример BitmapSpeed 31
1.3. Обобщающие примеры 33
1.3.1. Обобщающий пример 1 — Информация о процессах 33
1.3.1.1. Получение списка процессов 33
1.3.1.2. Получение списка и свойств окон 33
1.3.2. Обобщающий пример 2 — Ассоциированные файлы и предотвращение запуска второй копии приложения 34
1.3.2.1. Ассоциирование расширения с приложением 34
1.3.2.2. Командная строка 35
1.3.2.3. Поиск уже запущенной копии приложения 35
1.3.2.4. Перевод приложения на передний план 36
1.3.3. Обобщающий пример 3 — «Дырявое» окно 37
1.3.3.1. Сообщение WM_NCHCHITTEST 37
1.3.3.2. Регионы 37
1.3.3.3. Сообщения WM_SIZE и WM_SIZING 37
1.3.3.4. А теперь — все вместе 38
1.3.4. Обобщающий пример 4 — Линии нестандартного стиля 39
1.3.4.1. Получение координат точек прямой 39
1.3.4.2. «Резиновая» линия и растровые операции 40
1.3.4.3. Кривые Безье 40
1.3.4.4. Траектории 41
1.3.4.5. Интерактивная кривая 42
Глава 2: Использование сокетов Delphi 43
2.1. Стандартные сокеты 44
2.1.1 Соглашения об именах 44
2.1.2. Общие сведения о сокетах 44
2.1.3. Сетевые протоколы. Семиуровневая модель OSI 45
2.1.4. Стек TCP/IP 45
2.1.5. Протокол UDP 46
2.1.6. Протокол TCP 47
2.1.7. Сетевые экраны 48
2.1.8. Создание сокета 48
2.1.9. Передача данных при использовании UDP 51
2.1.10. Пример программы: простейший чат на UDP 53
2.1.11. Передача данных при использовании TCP 55
2.1.12. Примеры передачи данных с помощью TCP 56
2.1.13. Определение готовности сокета 59
2.1.14. Примеры использования функции select 61
2.1.15. Неблокирующий режим 63
2.1.16. Сервер на неблокирующих сокетах 65
2.1.17. Параметры сокета 67
2.1.18. Итоги первого раздела 68
2.2. Сокеты Windows 68
2.2.1. Версии Windows Sockets 68
2.2.2. Устаревшие функции WinSock 1 68
2.2.3. Информация о протоколе 69
2.2.4. Новые функции 70
2.2.5. Асинхронный режим, основанный на сообщениях 72
2.2.6. Пример сервера, основанного на сообщениях 74
2.2.7. Асинхронный режим, основанный на событиях 77
2.2.8. Пример использования сокетов с событиями 79
2.2.9. Перекрытый ввод-вывод 84
2.2.10. Сервер, использующий перекрытый ввод-вывод 87
2.2.11. Многоадресная рассылка 89
2.2.12. Дополнительные функции 91
2.3. Итоги главы 92
Глава 3: «Подводные камни» 93
3.1. Неочевидные особенности целых чисел 93
3.1.1. Аппаратное представление целых чисел 93
3.1.2. Выход за пределы диапазона при присваивании 94
3.1.3. Переполнение при арифметических операциях 94
3.1.4. Сравнение знакового и беззнакового числа 95
3.1.5. Неявное преобразование в цикле for 95
3.2. Неочевидные особенности вещественных чисел 95
3.2.1. Двоичные дроби 95
3.2.2. Вещественные типы Delphi 96
3.2.3. Внутренний формат вещественных чисел 96
3.2.4. «Неполноценный» Extended 97
3.2.5. Бесконечные дроби 97
3.2.6. «Неправильное» значение 97
3.2.7. Сравнение 98
3.2.8. Сравнение разных типов 98
3.2.9. Вычитание в цикле 98
3.2.10. Неожиданная потеря точности 98
3.2.11. Борьба с потерей точности в VCL 99
3.2.12. Машинное эпсилон 99
3.2.13. Методы решения проблем 99
3.3. Тонкости работы со строками 100
3.3.1. Виды строк в Delphi 100
3.3.2. Хранение строковых литералов 100
3.3.3. Приведение литералов к типу PChar 101
3.3.4. Сравнение строк 102
3.3.5. Побочное изменение 103
3.3.6. Нулевой символ в середине строки 104
3.3.7. Функция, возвращающая AnsiString 104
3.3.8. Строки в записях 104
3.3.9. Использование ShareMem 107
3.4. Прочие «подводные камни» 108
3.4.1. Порядок вычисления операндов 108
3.4.2. Зацикливание обработчика TUpDown.OnClick при открытии диалогового окна в обработчике 109
3.4.3. Access violation при закрытии формы с перекрытым методом WndProc 109
3.4.4. Подмена имени оконного класса, возвращаемого функцией GetClassInfo 110
3.4.5. Ошибка EReadError при использовании вещественных свойств 111
3.4.6. Ошибка List index out of bounds при корректном значении индекса 111
3.4.7. Неправильное поведение свойства Anchors 112
3.4.8. Ошибка при сравнении указателей на метод 112
3.4.9. Возможность получения адреса свойства 113
3.4.10. Невозможность использования некоторых свойств оконного компонента в деструкторе 113
Глава 4: Разбор и вычисление выражений 115
4.1. Синтаксис и семантика 115
4.2. Формальное описание синтаксиса 116
4.3. Синтаксис вещественного числа 117
4.4. Простой калькулятор 117
4.5. Учет приоритета операторов 118
4.6. Выражения со скобками 119
4.7. Полноценный калькулятор 120
4.8. Калькулятор с лексическим анализатором 121
4.9. Однопроходный калькулятор и функции с несколькими переменными 123
4.10. Еще немного теории 125
Приложение 1: Сайт «Королевство Delphi» 126
Приложение 2: Содержимое компакт-диска 128
Примеры к главе 1 128
Примеры к главе 2 129
Примеры к главе 3 129
Примеры к главе 4 130
Список литературы 130
Илон Маск рекомендует:  Asp методы объектов контейнеров adsi

Лучшие электронные книги в формате fb2
Наш портал – это библиотека интересных электронных книг разнообразных жанров. Здесь вы найдете произведения как российских, так и зарубежных писателей. Все электронные книги, представленные на нашем сайте, можно скачать бесплатно. Наша библиотека содержит только лучшие бесплатные электронные книги, ведь каждую электронную книгу мы тщательно изучаем перед добавлением в базу. Мы выбираем интереснейшие произведения в удобном формате fb2, все они достойны вашего внимания. Чтение электронных книг наверняка принесет вам удовольствие. Всё что, что вам нужно сделать, — найти и скачать книгу, которая понравится вам по заголовку и описанию.
Библиотека fb2-электронных книг – полезнейшее изобретение человечества. Для того чтобы, читать книгу, вам нужно просто загрузить ее с нашего сайта. Вы можете наслаждаться чтением, не совершая лишние траты. Электронная книга, в отличие от бумажной, обладает множеством преимуществ. Вы экономите время и силы, не совершая утомительные походы по магазинам. Вам также не нужно обременять себя ношением тяжеловесной макулатуры. Скачать и читать электронную книгу легко и просто . Мы позаботились о том, чтобы вам всегда было что почитать. Электронная книга fb2 принесет вам море положительных эмоций: она способна поделиться с вами мудростью, поднять настроение или просто скрасить досуг.

DelphiComponent.ru — бесплатно видеоуроки по Delphi, статьи, исходники

Вещественные типы (Действительные типы) в Delphi XE

Значение переменных вещественного типа всегда приблизительные, по­этому их нельзя проверять на равенство!

-2.9×10 -39 ..1.7×10 38

-1.5×10 -45 ..3.4×10 38

-5.0×10 -324 ..1.7×10 3U8

-3.6×10 -4951 «1.1×10 4y32

-2×10 63 +1 ..2×10 63 -1

Тип Real 48 оставлен только для совместимости с предыдущими версиями Delphi , поэтому его не следует использовать.

Типы Comp и Currency используются только в денежных операциях.

Обычно для расчётов хватает точности типа Single , но вычисления произ­водятся быстрее с типом Real (он же Double ).

Для записи вещественных чисел используют 2 способа. Первый — как в школе, но вместо десятичной запятой ставится точка:

Для очень больших и очень маленьких чисел больше подходит второй способ. Сначала записывается однозначное число с десятичной точкой, за­тем буква E (или е) и целое число, которое равно степени десятки. Напри­мер,

Объявление переменных вещественного типа:

Вещественные числа часто используются для «технических» расчётов, а при необходимости их можно округлить до целых чисел (тип результата — int 64) с помощью функций trunc и round .

Целым переменным нельзя присваивать действительные значения!

Функция trunc просто отсекает дробную часть числа:

Функция round округляет действительное число до ближайшего целого:

Чтобы было легче понять, как действует функция round , выразим её через trunc :

Simple Types (Delphi)

Contents

Simple types — which include ordinal types and real types — define ordered sets of values.

Ordinal Types

Ordinal types include integer, character, Boolean, enumerated, and subrange types. An ordinal type defines an ordered set of values in which each value except the first has a unique predecessor and each value except the last has a unique successor. Further, each value has an ordinality, which determines the ordering of the type. In most cases, if a value has ordinality n, its predecessor has ordinality n-1 and its successor has ordinality n+1.

For integer types, the ordinality of a value is the value itself. Subrange types maintain the ordinalities of their base types. For other ordinal types, by default the first value has ordinality 0, the next value has ordinality 1, and so forth. The declaration of an enumerated type can explicitly override this default.

Several predefined functions operate on ordinal values and type identifiers. The most important of them are summarized below.

-2147483648..2147483647
(-2 31 ..2^ 31 -1)

-9223372036854775808..9223372036854775807
(-2 63 ..2 63 -1)

0..4294967295
(0..2 32 -1)

0..18446744073709551615
(0..2 64 -1)

-2147483648..2147483647
(-2 31 ..2 31 -1)

-9223372036854775808..9223372036854775807
(-2 63 ..2 63 -1)

0..4294967295
(0..2 32 -1)

0..18446744073709551615
(0..2 64 -1)

Type Platform Range Format Alias
32-bit platforms
64-bit platforms 32-bit platforms
64-bit platforms Unsigned 64-bit UInt64
32-bit platforms and 64-bit Windows platforms
64-bit POSIX platforms include iOS and Linux Signed 64-bit Int64
32-bit platforms and 64-bit Windows platforms
64-bit POSIX platforms include iOS and Linux UInt64

Note: 32-bit platforms include 32-bit Windows, 32-bit macOS, 32-bit iOS, iOS Simulator and Android.

Platform-Independent Integer Types

Platform-independent integer types always have the same size, regardless of what platform you use. Platform-independent integer types include ShortInt, SmallInt, LongInt, Integer, Int64, Byte, Word, LongWord, Cardinal, and UInt64.

Platform-independent integer types

A value of type ByteBool, LongBool, or WordBool is considered True when its ordinality is nonzero. If such a value appears in a context where a Boolean is expected, the compiler automatically converts any value of nonzero ordinality to True.

The previous remarks refer to the ordinality of Boolean values, not to the values themselves. In Delphi, Boolean expressions cannot be equated with integers or reals. Hence, if X is an integer variable, the statement:

generates a compilation error. Casting the variable to a Boolean type is unreliable, but each of the following alternatives will work.

Enumerated Types

An enumerated type defines an ordered set of values by simply listing identifiers that denote these values. The values have no inherent meaning. To declare an enumerated type, use the syntax:

where typeName and each val are valid identifiers. For example, the declaration:

defines an enumerated type called Suit , whose possible values are Club , Diamond , Heart , and Spade , where Ord(Club) returns 0, Ord(Diamond) returns 1, and so on.

When you declare an enumerated type, you are declaring each val to be a constant of type typeName . If the val identifiers are used for another purpose within the same scope, naming conflicts occur. For example, suppose you declare the type:

Unfortunately, Click is also the name of a method defined for TControl and all of the objects in VCL that descend from it. So if you are writing an application and you create an event handler like:

you will get a compilation error; the compiler interprets Click within the scope of the procedure as a reference to a Click method of a TForm. You can work around this by qualifying the identifier; thus, if TSound is declared in MyUnit, you would use:

A better solution, however, is to choose constant names that are not likely to conflict with other identifiers. Examples:

You can use the (val1, . valn) construction directly in variable declarations, as if it were a type name:

But if you declare MyCard this way, you cannot declare another variable within the same scope using these constant identifiers. Thus:

generates a compilation error. But:

compiles cleanly, as does:

Enumerated Types with Explicitly Assigned Ordinality

By default, the ordinalities of enumerated values start from 0 and follow the sequence in which their >

defines a type called Size whose possible values include Small , Medium , and Large , where Ord(Small) returns 5, Ord(Medium) returns 10, and Ord(Large) returns 15.

An enumerated type is, in effect, a subrange whose lowest and highest values correspond to the lowest and highest ordinalities of the constants in the declaration. In the previous example, the Size type has 11 possible values whose ordinalities range from 5 to 15. (Hence the type array[Size] of Char represents an array of 11 characters.) Only three of these values have names, but the others are accessible through typecasts and through routines such as Pred, Succ, Inc, and Dec. In the following example, «anonymous» values in the range of Size are assigned to the variable X .

Any value that is not explicitly assigned an ordinality has the ordinality one greater than that of the previous value in the list. If the first value is not assigned an ordinality, its ordinality is 0. Hence, given the declaration:

SomeEnum has only two possible values: Ord(e1) returns 0, Ord(e2) returns 1, and Ord(e3) also returns 1; because e2 and e3 have the same ordinality, they represent the same value.

Enumerated constants without a specific value have RTTI:

whereas enumerated constants with a specific value, such as the following, do not have RTTI:

Scoped Enumerations

You can use scoped enumerations in Delphi code if you enable the compiler directive.

For instance, let us define the following unit in the Unit1.pas file

and the following program using this unit

First, Run (F9) on this code. The code runs successfully. This means that the First identifier, used in the

variable, is the global scope identifier introduced in the

Now clear comment from the

compiler directive in the unit1 unit. This directive enforces the TMyEnum enumeration to be scoped. Execute Run. The E2003 Undeclared identifier ‘First’ error is generated on the

line. It informs that the <$SCOPEDENUMS ON>compiler directive prevents the First identifier, introduced in the scoped TMyEnum enumeration, to be added to the global scope.

To use identifiers introduced in scoped enumerations, prefix a reference to an enumeration’s element with its type name. For example, clear comment in the second

version of the Value variable (and comment the first version of Value ). Execute Run. The program runs successfully. This means that the First identifier is known in the TMyEnum scope.

Now comment the

compiler directive in unit1 . Then clear comment from the declaration of the First variable

and again use the

variable. Now the code in the program Project1 looks like this:

Execute Run. The

line causes the E2010 Incompatible types — ‘TMyEnum’ and ‘Integer’ error. This means that the naming conflict occurs between the global scope First identifier introduced in the TMyEnum enumeration and the First variable. You can work around this conflict by qualifying the First identifier with the unit1 unit in which it is defined. For this, comment again the first version of Value variable and clear comment from the third one:

Execute Run. The program runs successfully. That is, now the First identifier can be qualified with the unit1 unit scope. But what happens if we again enable the

compiler directive in unit1 . The compiler generates the E2003 Undeclared identifier ‘First’ error on the

line. This means that prevents adding the First enumeration’s identifier in the unit1 scope. Now the First identifier is added only in the TMyEnum enumeration’s scope. To check this, let us again use the

version of the Value variable. Execute Run and the code succeeds.

Subrange Types

A subrange type represents a subset of the values in another ordinal type (called the base type). Any construction of the form Low..High , where Low and High are constant expressions of the same ordinal type and Low is less than High , identifies a subrange type that includes all values between Low and High . For example, if you declare the enumerated type:

you can then define a subrange type like:

Here TMyColors includes the values Green , Yellow , Orange , Purple , and White .

You can use numeric constants and characters (string constants of length 1) to define subrange types:

When you use numeric or character constants to define a subrange, the base type is the smallest integer or character type that contains the specified range.

The LowerBound..UpperBound construction itself functions as a type name, so you can use it directly in variable declarations. For example:

declares an integer variable whose value can be anywhere in the range from 1 through 500.

The ordinality of each value in a subrange is preserved from the base type. (In the first example, if Color is a variable that holds the value Green , Ord(Color) returns 2 regardless of whether Color is of type TColors or TMyColors.) Values do not wrap around the beginning or end of a subrange, even if the base is an integer or character type; incrementing or decrementing past the boundary of a subrange simply converts the value to the base type. Hence, while:

produces an error, the following code:

assigns the value 100 to I (unless compiler range-checking is enabled).

The use of constant expressions in subrange definitions introduces a syntactic difficulty. In any type declaration, when the first meaningful character after = is a left parenthesis, the compiler assumes that an enumerated type is being defined. Hence the code:

produces an error. Work around this problem by rewriting the type declaration to avoid the leading parenthesis:

Real Types

A real type defines a set of numbers that can be represented with the floating-point notation. The table below gives the ranges and storage formats for the real types on 64-bit and 32-bit platforms.

Boolean ByteBool, WordBool, LongBool
Extended
32bit Intel Windows 3.37e-4932 .. 1.18e+4932 10-20 10
64-bit Intel Linux
32-bit Intel macOS
32-bit Intel iOS Simulator
3.37e-4932 .. 1.18e+4932 10-20 16
other platforms 2.23e-308 .. 1.79e+308 15-16 8
Comp all -9223372036854775807.. 9223372036854775807
(-2 63 +1.. 2 63 -1)
10-20 8
Currency all -922337203685477.5807.. 922337203685477.5807 10-20 8

The following remarks apply to real types:

  • Real is equivalent to Double, in the current implementation.
  • Real48 is maintained for backward compatibility. Since its storage format is not native to the Intel processor architecture, it results in slower performance than other floating-point types.

The 6-byte Real48 type was called Real in earlier versions of Object Pascal. If you are recompiling code that uses the older, 6-byte Real type in Delphi, you may want to change it to Real48. You can also use the compiler directive to turn Real back into the 6-byte type.

  • Extended offers greater precision on 32-bit platforms than other real types.

On 64-bit platforms Extended is an alias for a Double; that is, the size of the Extended data type is 8 bytes. Thus you have less precision using an Extended on 64-bit platforms compared to 32-bit platforms, where Extended is 10 bytes. Therefore, if your applications use the Extended data type and you rely on precision for floating-point operations, this size difference might affect your data. Be careful using Extended if you are creating data files to share across platforms. For more information, see The Extended Data Type Is 2 Bytes Smaller on 64-bit Windows Systems.

  • The Comp (computational) type is native to the Intel processor architecture and represents a 64-bit integer. It is >See Also

    В Delphi как определить, когда использовать Real, Real48, Double или Single типы данных?

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

    Если я использую базу данных для хранения этих значений, и я определил поля в этой базе данных как десятичное значение с двумя десятичными знаками, какой тип данных Delphi наиболее совместим с этим сценарием?

    Должен ли я использовать формулу округления в Delphi для форматирования результатов до двух десятичных знаков перед сохранением значений в базе данных? Если да, то для чего это лучше всего?

    Для таких вычислений не используйте типы с плавающей запятой, такие как Real, Single или Double. Они не хороши с десятичными значениями, такими как 0,01 или 1234,995, поскольку они должны их приближать.

    Вы можете использовать валюту, тип фиксированной точки, но это все еще ограничено 4 знаками после запятой.

    Попробуйте мой Decimal тип, который имеет 28-29 мест и имеет десятичный показатель, поэтому он идеально подходит для таких вычислений. Единственным недостатком является то, что он не поддерживается FPU (но написан на ассемблере, тем не менее), поэтому он не так быстро, как встроенные типы. Это то же самое, что и тип Decimal, используемый в .NET(но немного быстрее) и очень похож на тот, который используется на Mac.

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

    Single — Тип Delphi

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

    s1.iY присваивается значение не 5.2 а 5.1999998093, когда присваиваю 6.3 то вместо 6.3 присваивается 6.3000001907.

    От: Smirnov.Anton
    Дата: 23.04.05 09:54
    Оценка:
    От: Anatoly Podgoretsky http://www.podgoretsky.com
    Дата: 23.04.05 10:01
    Оценка:

    Здравствуйте, Аноним, Вы писали:
    А> iY :Single;

    А> s1.iY := 5.2;
    А>s1.iY присваивается значение не 5.2 а 5.1999998093, когда присваиваю 6.3 то вместо 6.3 присваивается 6.3000001907.

    Это число невозможно представить точно ни а одном из допустимых типов с плавающей запятой, это наиболее близкое значение к 5.2

    От: klovetski
    Дата: 23.04.05 11:14
    Оценка:

    Здравствуйте, Аноним, Вы писали:

    А>Добырый день.Подскажите пожалуйста почему когда переменной присваиваю тип Single, то операции присваивания значений выполняются неправильно:
    А>

    А>s1.iY присваивается значение не 5.2 а 5.1999998093, когда присваиваю 6.3 то вместо 6.3 присваивается 6.3000001907.

    Fundamental real types

    Type Range Significant digits Size in bytes
    Real48 2.9 x 10^-39 .. 1.7 x 10^38 11-12 6

    Single 1.5 x 10^-45 .. 3.4 x 10^38 7-8 4

    Double 5.0 x 10^-324 .. 1.7 x 10^308 15-16 8
    Extended 3.6 x 10^-4951 .. 1.1 x 10^4932 19-20 10
    Comp -2^63+1 .. 2^63 -1 19-20 8
    Currency -922337203685477.5808.. 922337203685477.5807 19-20 8

    Как и обещано, для типа Single 7 знаков даются точно.

    От: Dimonka
    Дата: 25.04.05 07:50
    Оценка:

    Здравствуйте, Аноним, Вы писали:

    А>s1.iY присваивается значение не 5.2 а 5.1999998093, когда присваиваю 6.3 то вместо 6.3 присваивается 6.3000001907.

    Когда сравниваешь числа с плавающей точкой, сравнивай их с заданной точностью:

    От: SergeyL
    Дата: 25.04.05 13:40
    Оценка:

    Здравствуйте, Dimonka, Вы писали:

    D>Здравствуйте, Аноним, Вы писали:

    А>>s1.iY присваивается значение не 5.2 а 5.1999998093, когда присваиваю 6.3 то вместо 6.3 присваивается 6.3000001907.

    D>Когда сравниваешь числа с плавающей точкой, сравнивай их с заданной точностью:
    D>
    D>

    Не знаю как в дельфи, а в билдере сравнение работает нормально, если использовать float-овую константу ( 5.2f ):

    От: Dimonka
    Дата: 25.04.05 15:09
    Оценка:

    Здравствуйте, SergeyL, Вы писали:

    SL>Не знаю как в дельфи, а в билдере сравнение работает нормально, если использовать float-овую константу ( 5.2f ):
    SL>

    Single занимает 4 байта, а float, на сколько я понимаю, все 8. Так что их так просто не прировняешь.

    От: Аноним
    Дата: 25.04.05 15:14
    Оценка: +1

    Здравствуйте, SergeyL, Вы писали:

    SL>Здравствуйте, Dimonka, Вы писали:

    D>>Здравствуйте, Аноним, Вы писали:

    А>>>s1.iY присваивается значение не 5.2 а 5.1999998093, когда присваиваю 6.3 то вместо 6.3 присваивается 6.3000001907.

    D>>Когда сравниваешь числа с плавающей точкой, сравнивай их с заданной точностью:
    D>>
    D>>

    SL>Не знаю как в дельфи, а в билдере сравнение работает нормально, если использовать float-овую константу ( 5.2f ):
    SL>

    Это тебе кажется.
    Так сравнивать нельзя ни на дебилдере, ни на дельфях,
    ти на вижуале.
    Вернее можно, но результат будет не тот, что ожидается.
    Ты же на самом деле никогда не сравниваешь 2 константы
    в стиле

    Сравнивают все же значение, полученное в результате
    вычислений с неким другим значением.
    В случае чисел с плавающей точкой сравнивать всегда надо с учетом некой окресности.

    От: SergeyL
    Дата: 26.04.05 08:25
    Оценка:

    Здравствуйте, Аноним, Вы писали:

    А>Ты же на самом деле никогда не сравниваешь 2 константы
    А>в стиле

    А>

    А>Сравнивают все же значение, полученное в результате
    А>вычислений с неким другим значением.
    А>В случае чисел с плавающей точкой сравнивать всегда надо с учетом некой окресности.

    Само собой, в реальной жизни точное сравнение чисел с плавающей точкой не имеет смысла.
    Я только говорю что это В ПРИНЦИПЕ возможно:

    От: Sinclair http://corp.ingrammicro.com/Solutions/Cloud.aspx
    Дата: 26.04.05 09:27
    Оценка: 7 (2)

    Здравствуйте, SergeyL, Вы писали:

    SL>Само собой, в реальной жизни точное сравнение чисел с плавающей точкой не имеет смысла.
    SL>Я только говорю что это В ПРИНЦИПЕ возможно:
    SL>
    Братан, этот пример не более полезен чем попытка вычислить предел выражения [1 / (x — const)] при x -> const при помощи поворота const на 90 градусов. Да, для const = 8 это сработает. Что, следуя твоей логике, показывает, что это В ПРИНЦИПЕ возможно.

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

    Увы — select count(x) вовсе не считает количество вхождений символа ‘x’ в таблице .

    От: SergeyL
    Дата: 27.04.05 06:51
    Оценка:

    Здравствуйте, Dimonka, Вы писали:

    D>Single занимает 4 байта, а float, на сколько я понимаю, все 8. Так что их так просто не прировняешь.

    float занимает 4 байта.

    От: SergeyL
    Дата: 27.04.05 07:06
    Оценка:

    Здравствуйте, Sinclair, Вы писали:

    S>select count(*) from table1 — В ПРИНЦИПЕ возможно:
    >>5
    S>select count(+) from table1
    >>syntax error —ожидали 3.
    S>[/sql]
    S>Увы — select count(x) вовсе не считает количество вхождений символа ‘x’ в таблице

    Прикольные примеры.
    Только у меня фокус не в повороте на 90 градусов. 5.2f — это float, а 5.2 — это double. Соответственно при сравнении (и не только) с double-овой константой float-овая переменная приводится к double.

    if either operand is of type double, the other operand is converted to double

    От: Sinclair http://corp.ingrammicro.com/Solutions/Cloud.aspx
    Дата: 27.04.05 07:31
    Оценка:
    От: SergeyL
    Дата: 27.04.05 07:59
    Оценка:

    Здравствуйте, Sinclair, Вы писали:

    S>Не хитри. Весь фокус у тебя в том, что ты взял числа, кратные 2. Они-то как раз представимы в IEEE формате без потерь. Благодаря этому срабатывает сравнение «а» с восьмеркой. С константами некратными 2 фокус не пройдет.

    От: Danchik
    Дата: 27.04.05 10:14
    Оценка:

    Здравствуйте, SergeyL, Вы писали:

    SL>Здравствуйте, Sinclair, Вы писали:

    S>>Не хитри. Весь фокус у тебя в том, что ты взял числа, кратные 2. Они-то как раз представимы в IEEE формате без потерь. Благодаря этому срабатывает сравнение «а» с восьмеркой. С константами некратными 2 фокус не пройдет.

    SL>

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

    Для того что бы не терялся precision в базах данных используется BCD тип. Почитай себе на досуге что это такое и зачем это сделано.

    » Delphi Single to Dword

    Добрый день, друзья!

    Подскажите как преобразовать средствами Delphi тип Single в Dword ?

    Single -это вещественный
    dword — два слова, два ворда описывают single , а одним word-om не опишешь, да.

    Вот я нашел обратную процедуру , из dword в single:

    Код:
    function NumToFloat(dwNum: DWORD): String;
    const
    EXP_BIAS = 127;
    var
    sFloat: String;
    dwFloat: Cardinal;
    snglFloat: Single; // 4 байта
    bySign, byExp: Byte;
    dwFractPart: Cardinal;
    snglFractPart: Single;
    begin
    dwFloat:= dwNum;
    bySign:= (dwFloat shr 31) and $1;
    byExp:= Byte((dwFloat shr 23) and $FF);
    if byExp = $FF then
    begin
    // ShowMessage(‘Infinity or Nan’);
    Result:= ‘Infinity or Nan’;
    end
    else
    if byExp = $00 then
    begin
    // ShowMessage(‘0 (Zero) or Denormal’);
    Result:= ‘0 (Zero) or Denormal’;
    end
    else
    begin
    dwFractPart:= Cardinal( ( Cardinal(dwFloat shl 9) shr 9 ) );

    // 10 бит точность — тысячные доли — итоговая точность сотые доли
    snglFractPart:= 1.0 +
    ((dwFractPart shr 22) and $1) * 0.5 +
    ((dwFractPart shr 21) and $1) * 0.25 +
    ((dwFractPart shr 20) and $1) * 0.125 +
    ((dwFractPart shr 19) and $1) * 0.0625 +
    ((dwFractPart shr 18) and $1) * 0.03125 +
    ((dwFractPart shr 17) and $1) * 0.015625 +
    ((dwFractPart shr 16) and $1) * 0.0078125 +
    ((dwFractPart shr 15) and $1) * 0.00390625 +
    ((dwFractPart shr 14) and $1) * 0.001953125 +
    ((dwFractPart shr 13) and $1) * 0.0009765625 +
    // Максимальная точность
    ((dwFractPart shr 12) and $1) * 0.00048828125 +
    ((dwFractPart shr 11) and $1) * 0.000244140625 +
    ((dwFractPart shr 10) and $1) * 0.0001220703125 +
    ((dwFractPart shr 9) and $1) * 0.00006103515625 +
    ((dwFractPart shr 8) and $1) * 0.000030517578125 +
    ((dwFractPart shr 7) and $1) * 0.0000152587890625 +
    ((dwFractPart shr 6) and $1) * 0.00000762939453125 +
    ((dwFractPart shr 5) and $1) * 0.000003814697265625 +
    ((dwFractPart shr 4) and $1) * 0.0000019073486328125 +
    ((dwFractPart shr 3) and $1) * 0.00000095367431640625 +
    ((dwFractPart shr 2) and $1) * 0.000000476837158203125 +
    ((dwFractPart shr 1) and $1) * 0.0000002384185791015625 +
    ( dwFractPart and $1) * 0.00000011920928955078125;

    snglFloat:= Power(-1, bySign) * Power(2.0, (byExp — EXP_BIAS)) * snglFractPart;
    sFloat:= FloatToStr(snglFloat);
    // ShowMessage(sFloat);
    end;
    Result:= sFloat;
    end;

    Типы данных Delphi и работа с ними

    К встроенным типам данных в языке Delphi относятся типы целые, действительные, символы, строки, указатели, булевы.

    Порядковые типы. Порядковыми (ordinal) типами называются те, в которых значения упорядочены, и для каждого из них можно указать предшествующее и последующее значения.

    Структурные типы. К структурным типам относятся множества, массивы, записи, файлы, классы, интерфейсы.

    Целые типы данных. В переменных целых типов информация представляется в виде целых чисел, т.е. чисел не имеющих дробной части.

    Таблица 1 Операции над порядковыми типами

    Минимальное значение порядкового типа Т

    Максимальное значение порядкового типа Т

    Порядковый номер значения выражения порядкового типа. Для целого выражения — просто его значение. Для остальных порядковых типов Ord возвращает физическое представление результата выражения, трактуемое как целое число. Возвращаемое значение всегда принадлежит одному из целых типов

    Предыдущее по порядку значение. Для целых выражений эквивалентно Х-1

    Следующее по порядку значение. Для целых выражений эквивалентно Х+1

    Уменьшает значение переменной на 1. Эквивалентно V := Pred(V)

    Увеличивает значение переменной на 1. Эквивалентно V := Succ(V)

    8 битов, беззнаковый

    16 битов, беззнаковый

    32 бита, беззнаковый

    Также существует такой тип, как Integer, который эквивалентен типу LongInt. Его диапазон от -2147483648 до 21474836478. Занимает 4 байта в пямяти. Основными являются Integer и Cardinal, так что в большинстве случаев желательно использовать эти типы.

    Над целыми данными выполняются все операции, определенные для порядковых типов. Операции над целыми типами:

    Возвращает абсолютное целое значение Х

    Возвращает целую часть частного деления Х на Y

    Возвращает остаток частного деления Х на Y

    Возвращает булево True (истина), если Х — нечетное целое, и False (ложь) — в противном случае

    Действительные типы данных. В переменных действительных типов содержатся числа, состоящие из целой и дробной частей.

    Количество значащих цифр

    Основным, обеспечивающим максимальную производительность, является тип Real, который в настоящий момент эквивалентен типу Double.

    Таблица 5 Функции действительных типов

    Абсолютная величина х

    Косинус х (х выражается в радианах, а не в градусах)

    Экспоненциальная функция от х

    Дробная часть х

    Целая часть х. Несмотря на название, возвращает действительное значение (с плавающей запятой), т.е. просто устанавливает нуль в дробной части

    Натуральный логарифм от х

    Ближайшее к х целое значение. Возвращает значение целого типа. Условие «ближайшее к х» не работает, если верхнее и нижнее значения оказываются равноудаленными (например, если дробная часть точно равна 0,5). В этих случаях Delphi перекладывает решение на операционную систему. Обычно процессоры Intel решают эту задачу в соответствии с рекомендацией IEEE округлять в сторону ближайшего четного целого числа. Иногда такой подход называют «банкирским округлением»

    Квадрат х, т.е. X*X

    Квадратный корень от х

    Целая часть х. В отличие от Int, возвращающей

    Символьные типы данных. Символьные типы предназначены для хранения одного символа.

    Однобайтовые символы, упорядоченные в соответствии с расширенным набором символов ANSI

    Символы объемом в слово, упорядоченные в соответствии с международным набором символов UNICODE. Первые 256 символов совпадают с символами ANSI

    Булевы типы данных. Переменные булевых типов данных представляют логические значения, например, true (истина) и false (ложь).

    Таблица 7 Размеры переменных булевых типов

    2 байт (объем Word)

    4 байт (объем Longint)

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

    Массив, как и любая переменная программы, перед использованием должен быть объявлен в разделе объявления переменных. В общем виде инструкция объявления массива выгладит следующим образом:

    Имя: [нижний_индекс..верхний_индекс] of тип

    где: имя — имя массива;

    array — зарезервированное слово языка Delphi, обозначающее, что объявляемое имя является именем массива;

    нижний_индекс и верхний_индекс — целые константы, определяющие диапазон изменения индекса элементов массива и, неявно, количество элементов (размер) массива;

    Илон Маск рекомендует:  Статьи об основах создания сайтов
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL