logo To Foot
© J R Stockton, ≥ 2008-06-05

Pascal / Delphi / + Types.

No-Frame * Framed Index * Frame This
Links within this site :-

I'd be pleased to link to similar information for other major languages.

Simple Types

See also in Pascal Floating-Point Page.

The Table is formatted with <pre>; thus it can be printed via View Source. On some systems, Ctrl-MouseWheel will change font size.

FPC information from marcov@toad.stack.nl (Marco van de Voort) :-

Added the Borland compatible compiler FPC: (0.99.13 development snapshot 3 Nov 1999)

  F1 = FPC -So (As TP as possible)
  F2 = FPC     (32-bit TP-ish)
  F3 = FPC -S2 (Delphi-ish)
  F4 = FPC -Sd (As Delphi compatible as possible)
  F5 = FPC -Gp (GNU Pascal mode; largely unfinished)

String=AnsiString can be enabled for all modes afaik with {$H+} in source, or -Sh on the commandline.

TMT information by test with version 3.21/3.30


                                                       BYTES

               Turbo Pascal (inc. BP7)                       Delphi                            FPC           TMT
 Version      1   2   3   4   5   6   7      1   2   3   4   5   6   7   8   9  10      1   2   3   4   5     3

 byte         1   1   1   1   1   1   1   F  1   1   1   1   1   1   1   1   1          1   1   1   1   1     1
 shortint     -   -   -   1   1   1   1   F  1   1   1   1   1   1   ?                  1   1   1   1   1     1
 word         -   -   -   2   2   2   2   F  2   2   2   2   2   2   2   2   2          2   2   2   2   2     2
 smallint     -   -   -   -   -   -   -   F  2   2   2   2   2   2   ?                  -   -   2   2   -     2
 integer      2   2   2   2   2   2   2   G  2   4   4   4   4   4   ?                  2   2   4   4   2     2
 cardinal     -   -   -   -   -   -   -   G  2   4   4   4   4   4   4                  4   4   4   4   4     4
 longint      -   -   -   4   4   4   4   F  4   4   4   4   4   4   ?                  4   4   4   4   4     4
 longword     -   -   -   -   -   -   -      -   -   -   4   4   4   4   4   4       \                     /  4
 doubleword                                                                         \   4   4   4   4   4   /
 dword *      -   -   -   -   -   -   -      -   -   -   -   -   ?   4                                        4
 int64        -   -   -   -   -   -   -      -   -   -   8   8   8   8   8   8   8                            -
 uint64       -   -   -   -   -   -   -      -   -   -                           8

 enumerated               1   1   1   1      1   1   1   1   1   ?   *
 set                      *   *   *   *      *   *   *   *   *   *   *

 real         6   6   6   6   6   6   6      6   6   6   8   8   8   ?                  8   8   8   8   8     6
 real48       -   -   -   -   -   -   -      -   -   -   6   6   6   6                  -   -   -   -   -     -
 single       -   -   -   4   4   4   4      4   4   4   4   4   4   4   4   4          4   4   4   4   4     4
 double       -   -   -   8   8   8   8      8   8   8   8   8   8   8   8   8          8   8   8   8   8     8
 extended     -   -   -  10  10  10  10     10  10  10  10  10  10  10  10  10         10  10  10  10  10    10
 comp         -   -   -   8   8   8   8      8   8   8   8   8   8   8                  8   8   8   8   8     -
 currency     -   -   -   -   -   -   -      -   8   8   8   8   8   8                 still in alpha test    -

 variant      -   -   -   -   -   -   -      ?   ?  16  16? 16? 16? 16?

 (complex)    -   -   -   -   -   -   -      -   -   -   -   -   ?   ?

 boolean      1   1   1   1   1   1   1      1   1   1   1   1   1   1                  1   1   1   1   1     1
 bytebool     -   -   -   -   -   -   1      1   1   1   1   1   1   1   1   1          1   1   1   1   1     1
 wordbool     -   -   -   -   -   -   2      2   2   2   2   2   2   2   2   2          2   2   2   2   2     2
 longbool     -   -   -   -   -   -   4      4   4   4   4   4   4   4   4   4          4   4   4   4   4     4

 char         1   1   1   1   1   1   1      1   1   1   1   1   1   1                  1   1   1   1   1     1
 ansichar     -   -   -   -   -   -   -   F  -   1   1   1   1   1   1                  -   -   -   -   -     -
 widechar     -   -   -   -   -   -   -   F  -   2   2   2   2   2   2                  -   -   -   -   -     -

 pointer      -   -   -   4   4   4   4      4   4   4   4   4   4   4                  ?   ?   ?   ?   ?     4

 pchar        -   -   -   -   -  4+  4+     4+  4+  4+  4+  4+  4+  4+                  ?   ?   ?   ?   ?     4
 string       -   -   - 256 256 256 256    256   ?  $H  $H  $H  $H  $H                 $H  $H  $H  $H  $H   256
 string[N]  N+1 N+1 N+1 N+1 N+1 N+1 N+1    N+1 N+1 N+1 N+1 N+1 N+1 N+1                                  N+1
 shortstring  -   -   -   -   -   -   -      ? N+1 N+1 N+1 N+1 N+1 N+1                256 256 256 256 256   256
 ansistring                                                                           4+H 4+H 4+H 4+H 4+H     -
 longstring   -   -   -   -   -   -   -      - 4+H 4+H   ?   ?   ?   ?                 still in alpha test    -
 widestring   -   -   -   -   -   -   -      - 4+H 4+H   ?   ?   ? 4+H                 still in alpha test    -
 utf8string   -   -   -   -   -   -   -      -   -   -             4+H

 F = Fundamental   G = Generic   N = Declared Length   +H = plus Heap
 T5.5 = T5 ?   TPW1,TPW1.5?   BP7 = T7 = TPW7   $H option, 256 or 4+
 * For Set, Enumerated, and others, see the manuals; but in Delphi (>1?) no set takes 3 bytes.

Notes :-

E&OE - RSVP with additions or corrections!

Field Alignment within a Pascal/Delphi Record

Borland's Pascal records are always packed, without padding between fields.

In Delphi, when a record type is not packed, padding is added so that each field begins at an address which is suitably divisible, to optimise access speed. In at least Delphi 6, packing can be affected by the $A directive.

  Borland's
Pascals
Delphi Kylix .NET
1234567891011
Ordinals 1 ?? size of type (1,2,4,8) ??? Some-
times
8
? ? ? ? ?
Floats 4 if size = 4×N; else 2
Short String 1
Array as an element of the array
Record as largest alignment in record
Set size of type if 1,2,4; else 1
Others 4

(I have Pascal, D3 and TD2006; I'm told D4 aligns as D3).

Who knows more? RSVP.

Floating-Point

Floating-point work is generally not exact.

Floating-Point Formats (including IEEE)

Borland's Pascal/Delphi Floating-Point Types
Type single real double extended comp
Source IEEE Borland IEEE IEEE IEEE
Implementation FPU/Emulate Software FPU/Emulate FPU/Emulate FPU/Emulate
Length, Bytes 4 6 8 10 8
Resolution 7 sig digits 11 sig digits 15 sig digits 19 sig digits 1.0
Least > 0, Denorm 1.4×10-45 n/a 5.0×10-324 1.9×10-4951 n/a
Least > 0, Normal 1.2×10-38 2.9×10-39 2.3×10-308 3.4×10-4932 1.0
Biggest 3.4×10+38 1.7×10+38 1.7×10+308 1.1×10+4932 2.0+63-1.0
Notation Sign, Magn. Sign, Magn. Sign, Magn. Sign, Magn. Two's Comp.
Field Pattern S-E-F S-F-E S-E-F S-E-I-F S'-F'
Field Sizes, bits 1-8-23 1-39-8 1-11-52 1-15-1-63 1-63
Exponent Bias 127 129 1023 16383 n/a
(uses <sup> : x×x=x2?)
S, S' = Sign ; E = (biased) Exponent ; I = Integer-part (else use 1.); F, F' = Fraction-part
The formulae are in the manuals; most are in IEEE standard 754 (& 854?).
Note that, as for integers, the sign bit is in the highest byte.
The given range of each type, even comp, is for both positive and negative values; zero is also included in all ranges.
The range of comp is -9,223,372,036,854,775,808 to +9,223,372,036,854,775,807, matching Int64.
According to documentation, in TP4 (&BP7?), comp $8000000000000000 is NaN; in D3, it's -263
In the Field entries of the table, left-to-right corresponds to addresses High to Low; the S and S' bits are always the MSB of the high byte, as for other types

For all formats, when all fields are zero the number is a valid zero, and not negative. For the detailed interpretation and usage of the fields, for non-normals, Not-A-Numbers, and INFinities, see the language manual.

Delphi's "currency" type is just a 64-bit integer like "comp" - 2's complement - but with an implied decimal point; the I/O unit is Pounds, the actual resolution is one centi-penny.

Other IEEE Formats

IEEE 754 is IEC 559.

IEEE Standard 754 has a Web Page, with links.

The page Some Proposals for Revising ANSI/IEEE Std 754-1985 links to information on :-

The draft revisions include "quad precision" floats : the 128 bit format has 112 fraction bits.

C Formats

It seems that, often but not inevitably, C float is IEEE single, C double is IEEE double, and C long double is IEEE extended. But check for each system.

Conversion of Floating-Point to/from String

The standard Pascal/Delphi conversion routines may not be quite as accurate as one might think or wish, especially for extreme cases such as denormals.

See also Bit Representations of Number in JavaScript Miscellany 0.

Raw Hex

If a float is to be transferred via a text file, its bit-pattern can be converted, without reference to its construction, to/from printing characters. This can be either in Hex, using twice the storage, or in some larger base: 13 characters out of a set of 72 suffice with a little to spare; 16 out of 32 are *exactly* sufficient, and encode 2.5 bytes to 4.

Exact Decimal

John Herbster has code for conversion from a float to an exact decimal string, but the result is necessarily often lengthy. For details, try Google, seeking articles dated around and after Christmas 2002; also at Borland CodeCentral.

Legible Hex

A float value can be converted, exactly, to/from a moderately-compact fixed-length Hex string that gives a passably readable indication of its value. An Extended has one sign bit, 64 mantissa bits, and 15 exponent bits; so it can be represented by

  ±F.FFFF FFFF FFFF FFFF H±FFF

in which each Hex digit is shown at its largest value (NaNs, Infs and non-normals need more thought). Here H means "×16^", and the active bits in the last mantissa digit are only those of greater value than the highest "1" bit in the first digit (the position of that "1" encodes two exponent bits).

A test program containing preliminary versions of my conversion routines, working in Pascal 7 and Delphi 3 at least, is available via programs/ as hexfloat.(pas exe zip).

Do IEEE, or other, standards refer to any such thing?

Conversion to/from Pascal/Delphi Floating-Point

All data formats may be made readable by conversion to text strings, though there may be loss of accuracy for floating-point numbers. Other languages often use the IEEE Single and/or Double float formats, for which cases no conversion is needed.

To prepare data containing 6-byte/10-byte reals for easier reading in another language, use TP or BP or Delphi to read them and convert them to either IEEE Singles/Doubles or to ASCII strings. TP5.5 can be used, and is free; see Borland Pascal Procurement Page. Example :-

   var Vin : real { or real48 } ; Vout : double ;
   ...
   Vout := Vin ;

From 6-byte/10-byte Real

To read TP/BP/Delphi 6-byte reals in another language, read them as six bytes and manipulate the bits as needed. Either assemble them into the pattern of the destination type, or use arithmetic to accumulate the value, as in sixbytes.pas. With such methods, rounding errors might cause small differences.

Likewise now to read 10-byte extendeds, tenbytes.pas. Tests for NaN and Inf should be added to it.

From 4/6/8/10-byte Real

Those, and routines for Singles and Doubles (needed if the destination uses a non-standard format), are now together in floatval.pas. Tests for denorm, NaN and Inf should be added to it.

Programs sixbytes.pas tenbytes.pas may, therefore, be withdrawn.

To 6-byte Real

The program also now contains conversions from extended and double to six-byte real which do not use any true float arithmetic; these may be useful for translating into other languages, if there is a need in them to generate the six-byte format.

Values Represented Exactly

To be sorted out

The following can be deduced by careful consideration of the details of the floating-point formats given in the printed Pascal and Delphi manuals, which are more detailed than what I have above.

DRAFT

ISTM that it would be useful, for each of the float types, to have a precise verbal statement of exactly which values can be represented exactly.

Types single, real48, and double (AIUI) differ only in the lengths of exponent and mantissa (and in non-standard numbers); extended differs slightly; comp & currency differ.

Best to start with double-likes :-

Parameter       *       Type \ param :  B       M       L       H
table           *       Single          4       24      -127    +127
numbers are     *       Real48          6       40      -127    +127
GUESSED         *       Double          8       53      -1023   +1024
Size :-
A number occupies B bytes; 8×B bits; 256B possibilities.
Normal :-
Any number which is an integer in the range 0 to 2M-1 inclusive, multiplied by a power of 2 in the range 2L to 2H inclusive, is represented exactly.
Denorm :-
Any number which is an integer in the range 0 to 2?-1 inclusive, multiplied by 2?, is represented exactly.
Inf :-
Plus infinity is represented exactly.
NaN :-
Non-numbers : ## distinct non-negative values exist.
+/-
For every positive value, including zero, there is a corresponding negative value.

One should show that all of the 28B possibilities are included.

I HAVE NOT CHECKED THE VALUES OF M L & H ABOVE; first one should consider the principles. Perhaps 2M-1 should also be listed?

Integers

In the floating-point type named, all integers from zero up to the one given, inclusive, can be represented exactly; the next value cannot be :-

Type Upper Limit of Continuous Exactness
Single 224 16,777,216
Real48 240 1,099,511,627,776
Double 253 9,007,199,254,740,992
Extended 264+ +18,446,744,073,709,551,616 + 5 ???

It is a foundation on which one can build true explanations. For example, a user who has successfully compared constants of values such as 2.0, 77.0, 64.25 with Doubles of the "same" value, set either from constants or by exact simple calculation, needs a sound foundation to understand the result of a calculation equivalent to
  const X = 1.3 ; var Y : Double ; begin write(X=Y) end.

That needs to be worked on.

Country-Dependent Upper Case

The standard UpCase() function only converts the characters 'a' to 'z'; in each of the various codepages there are various other characters, such as 'æ' and accented ones, that can also be converted. In DOS 4.0 and up, subfunctions of Int21/65 can be used to convert characters, Pascal strings, and ASCIIZ strings; see Ralf Brown's Interrupt List.

Ralf Quint gave, in News, something like :-

  function UpCaseAll(C : char) : char ;
  var Regs : Registers ;
  begin
    Regs.AX := $6520 ;
    Regs.DL := byte(C) ;
    Intr($21, Regs) ;
    UpCaseAll := char(Regs.DL) ;
  end {UpCaseAll} ;

  procedure UpperAll(var S : string) ;
  var Regs : Registers ;
  begin
    Regs.AX := $6521 ;
    Regs.DS := Seg(S) ;
    Regs.DX := Ofs(S)+1 ;
    Regs.CX := Length(S) ;
    Intr($21, Regs) ;
  end {UpperAll} ;

For asm versions, see his news:c.l.p.b :-
Message-ID: <tq8bnugb76jpimli147ujce3cvl47krkfk@4ax.com>
Date: Tue, 03 Sep 2002 23:12:21 -0700

As far as I can see, these interrupts must use array lookup.

  for C := #0 to #255 do LoCaseAll[UpCaseAll(C)] := C ;

should be usable as preparation for the reverse operation.

Some Greek characters may be available in both cases; I don't know whether Int 21/65 recognises this.

Home Page
Mail: no HTML
© Dr J R Stockton, near London, UK.
All Rights Reserved.
These pages are tested mainly with MS IE 7 and Firefox 3.0 and W3's Tidy.
This site, http://www.merlyn.demon.co.uk/, is maintained by me.
Head.