Contents
A. Delphi/Kylix Math Unit | efg's Delphi Math Resources | |
B. Floating-Point Numbers, IEEE Math | efg's Delphi Math Functions | |
C. Delphi Math Tips and Tricks | efg's Mathematics Page |
Question | Answer | ||||||||||
A-1. Where is the Delphi Math unit? | The math unit is included in all versions of Delphi 4/5/6 and Kylix. The Delphi Math unit is available only with the Professional or Client/Server versions of Delphi 3 -- it is not available with the "Standard" version. It is also available with the Developer version of Delphi 2 and with the Client/Server versions of Delphi 1 or 2. You'll find the source code unit in directory ..\source\rtl\sys\math.pas. | ||||||||||
A-2. What's new in the Delphi/Kylix Math unit? |
| ||||||||||
A-3. What functions are in the Delphi 32 (i.e., Delphi 2 - 4) Math unit? (Note: [n] indicates function was new in Delphi n) |
Min and Max constants for Single, Double, Extended, Comp types Trig: ArcCos, ArcSin, ArcTan2, SinCos, Tan, CoTan, Hypot Angles: DegToRad, RadToDeg, GradToRad, RadToGrad, CycleToRad, RadToCycle Hyperbolic: Cosh, Sinh, Tanh, ArcCosh, ArcSinh, ArcTanh Logarithm: LnXP1, Log10, Log2, LogN Exponential: IntPower, Power Miscellaneous: Frexp, Ldexp, Ceil, Floor, Poly, EInvalidArgument type Statistical: Mean, Sum, SumInt [3], SumOfSquares, SumsAndSquares, MinValue, MinIntValue [3], Min overloads [4], MaxValue, MaxIntValue [3], Max overloads[4], StdDev, MeanAndStdDev, PopnStdDev, Variance, PopnVariance, TotalVariance, Norm, MomentSkewKurtosis, RandG Financial: TPaymentTIme type, DoubleDecliningBalance, FutureValue, InterestPayment, InterestRate, InternalRateOfReturn, NumberOfPeriods, NetPresentValue, Payment, PeriodPayment, PresentValue, SLNDepreciation, SYDDepreciation Note: Chapter 9, "The Shadowy Math Unit" in Kick Ass Delphi Programming | ||||||||||
A-4. Where can I find other Delphi/ Pascal math function libraries? | Delphi Math Functions Pages Source of Numerical Analysis Code in Pascal Jean Debord's TPMath page ESB Consultancy's ESBMaths Razor's Edge Software MathX SDL's (Software Development Lohninger) Math1 and Math2 |
B. Floating-Point Numbers, IEEE Math
Question | Answer | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
B-1. Overview Info | What Every Computer Scientist Should Know About Floating-Point Arithmetic http://docs.sun.com/source/806-3568/ncg_goldberg.html | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
B-2. What are the Object Pascal numeric ordinal types? |
Notes:
Thanks to Roman Krejci for correcting an error in the above table about the generic integer in Delphi versions 2-3. (2 Aug 1998) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
B-3. What are the floating-point data types? |
Notes:
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
B-4. How can I learn more about floating-point numbers? | See Borland's Tech Info 1027, An Overview of Floating Point Numbers, http://community.borland.com/article/0,1410,15855,00.html (The math in the article is OK, but the programming examples are in C, unfortunately.) The article "Reviewing Delphi by the numbers" in the April 1998 Delphi Developer's Journal (pp. 7-11) is a good overview of ordinal and floating-point types in Delphi. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
B-5. What is IEEE floating point? | IEEE-754 is a standard way to store floating point values on a variety of computers. The Single, Double and Extended data types are all stored in IEEE format. The older Real values are not stored in IEEE format.
See efg's NaN Tech Note IEEE Standard 754 Floating Point Numbers Formally Verifying IEEE Compliance of Floating-Point Hardware A German description of IEEE-754, Gleitkommazahlen nach IEEE, is available from http://www.informatik.uni-halle.de/lehre/pascal/sprache/pas_ieee.html. Future 64-bit Intel Architecture: IA-64 Floating-Point Operations and the IEEE Standard for Binary Floating-Point Arithmetic John Herbster's T_BinaryFloatingPoint program for analyzing the extended, double, and single binary point numbers. IEEE standard 754 for binary floating-point arithmetic | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
B-6. How can I convert my old Real values to IEEE doubles? | See Richard Biffl's BPREAL.C function and related files: BPReal.ZIP
To convert Turbo Pascal 3.0 BCD reals (10-byte binary coded decimal reals with 18 significant digits) to Turbo Pascal 5.0 floating point numbers, download Turbo Pascal 5.5 from the Borland Community Museum: http://community.borland.com/museum, and install it. Look for BCD.PAS in the Turbo3 directory. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
B-7. How can I convert between Microsoft Binary and IEEE format? Mac format? |
TI1431C, Converting between Microsoft Binary and IEEE format Mark Di Val's Usenet Post showing Microsoft's conversion functions (in C/C++) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
B-8. What is a NAN? How can I test for one? What is an INF value? How can I do arithmetic with NAN and INF values? | In IEEE math a NAN is "not a number," i.e., an undefined value. INF is infinity and can be positive or negative. Sample of easy way to define NAN and INF values: procedure TForm1.ButtonSpecialClick(Sender: TObject); CONST Infinity = 1.0/0.0; NaN = 0.0/0.0; begin // INF NAN ShowMessage(FloatToStr(Infinity) + ' ' + FloatToStr(NaN)) end; TI1716, Testing for Not a Number (NaN) Ray Lischner's math10.zip has some information about NANs and INFs but only compiles in Delphi 1. See IEEE754.TXT for a short Delphi 3 unit that defines NAN, PositiveInfinity, etc. and shows an example of how to use such values in expressions. (Also includes a DoubleToHex function to display doubles in logical hex format.) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
B-9. What is IEEE rounding? | efg's Set8087CW and SetRoundMode rounding example. See Set8087CW for examples.
The default IEEE rounding rule is to round to the nearest even integer. For example: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
B-10. How can I round a floating point number in the traditional way: below 0.5 rounds down, 0.5 and above, rounds up? | FAQ1814D.txt Explaination (sic) of rounding http://community.borland.com/article/0,1410,16814,00.html See Set8087CW for how to control rounding modes. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
B-11. When I do a StrToFloat('1234.5544') I get something like 1234.55440000000003. What is wrong here? |
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
B-12. I'm trying to compare two floating point numbers that should be equal. Why aren't the two values equal? |
TI2139, How to Compare Floating Point Numbers Numerical Accuracy 101 for Delphi Developers Typically, you can use relative or absolute comparisons to avoid problems with "fuzz" (a term used with the language APL) with floating-point numbers. Because of this "fuzz" with floating point numbers, comparison of two calculated floating point numbers should be based on either absolute or relative error. IF ABS( (CalculatedValue - TrueValue) / TrueValue ) < AcceptableRelativeError THEN ... where AcceptableRelativeError is application specific (and obviously TrueValue <> 0.0). HOWEVER, this form of comparision can lead to divide-by-zero problems. An alternative suggested in a UseNet Post by Hans-Bernhard Broeker avoids this problem by using: The Delphi 3 math unit performs relative comparisons like this (but it's not exposed in the unit's interface): FUNCTION RelSmall(X, Y: Extended): Boolean;
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
B-13. Explain how a comp type is a floating point type but is a 64-bit integer. (Note: Use the new Int64 type in Delphi 4 or later) |
Since the floating point unit (FPU) deals with this 64-bit integer, the comp type is treated as if it were a floating point type even though it is a 64-bit integer. Delphi's VCL defines a type called TLargeInteger type that has a QuadPart comp type but also a LowPart and HighPart that are LongInts. You can speed up conversion of a comp to an integer type using TLargeInteger. See Borland's Assigning a comp type to an integer (FAQ 1965D).
In D4 the TLargeInteger is an Int64, but through a pLargeInteger pointer the LowPart, HighPart and QuadPart of the Int64 can still be accessed like in D3. In D4 a TULargeInteger and a pULargeInteger are defined much like the TLargeInteger and pLargeInteger. The HighPart of a TULargeInteger is a DWORD (i.e., unsigned) while the HighPart of a TLargeInteger is a LongInt (i.e., signed). While not very intuitive, you must treat a comp type as a float when converting to a string. Specifically, you must use FloatToStr or FormatFloat to convert to a string. Consider the following example: VAR The resulting string, s, contains the following: 7FFFFFFFFFFFFFFF 2147483647 -1 9.22337203685477581E18 Another example of using TLargeInteger is in Using the WIN API high resolution performance counter (FAQ 2028D). | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
B-14. How can I get Delphi to perform stronger type checking on user defined types? | For example, how can I define a type that descends from a double but not pass this type to any function expecting a double (without a warning)?
See Borland FAQ 2126D, "Getting stronger type checking" | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
B-15. Unsigned 32 Integers for Delphi 2/3 | By Ray Lischner. The Unsigned unit implements unsigned 32-bit integer arithmetic: comparisons, conversions, and division. Freeware. Source code and help file included. In Delphi 1.0, you must also download the FltMath unit, in math10.zip. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
B-16. Floating Point Optimzation | Floating Point Optimization Guidelines www.optimalcode.com/float.htm |
C. Delphi Math Tips and Tricks
Topic | Tip or Trick |
C-1. Integer to Float | Simple assignment: x := i; |
C-2. Integer to String | s := IntToStr(i); or Format('%6.6d', [1234]) returns '001234' |
C-3. Float to Integer | TRUNC(3.5) = 3 or ROUND (see "IEEE Rounding" above) |
C-4. Float to String | Format, FormatFloat or FloatToStr, but also FloatToDecimal, FloatToStrF, FloatToText, FloatToTextFmt Examples: Format('%.3f times %d is %-16s', [Measurement, Value, Key]); // "C" sprintf format specifications FormatFloat('##0.0', Factor); FloatToStr(x); |
C-5. String To Float; Sting To Integer | If d is a double: d := StrToFloat('1234.5544'); If i is an integer: i := StrToInt('1234'); |
C-6. How can I localize numbers to display correctly in both the U.S. and European formats? What is the ThousandSeparator? What is the DecimalSeparator? |
VAR x: DOUBLE; i: INTEGER; BEGIN x := 1234567.8945; Button1.Caption := ThousandSeparator; ThousandSeparator := ','; DecimalSeparator := '.'; LabelUSA.Caption := FormatFloat('#,###,###.###', x); ThousandSeparator := '.'; DecimalSeparator := ','; LabelEuropean.Caption := FormatFloat('#,###,###.###', x); The resulting strings are (remember IEEE rounding rounds towards an even number): USA: 1,234,567.894 European: 1.234.567,894 Treat an integer the same way and use FormatFloat to get a ThousandSeparator in an integer string. |
C-7. Dynamically allocated arrays (one dimension) | Arrays are incredibly useful and crop up in just about every project we create. But “out of the box” they are rather inflexible as you need to decide upfront how big your array should be. Not any more, Brian Long explains how to make your arrays dynamic: resizeable and powerful, for Delphi 1 right through to Delphi 4, with its new built-in dynamic arrays feature. Delphi Magazine, Issue 37, September 1998 How to Create an Array of 2,000,000 doubles in Delphi 1: Delphi1LargeArray.ZIP Also, see example below in "Open Array; Slice Function." Also look at Borland's Tech Info Report, Dynamically Allocating Arrays: Dr. Dobb's Journal on huge arrays in Turbo Pascal: ftp://garbo.uwasa.fi/pc/turbopas/ddj8803.zip Dr. Dobb's Journal on virtual arrays in Turbo Pascal: ftp://garbo.uwasa.fi/pc/turbopas/ddj8810.zip |
C-8. 2D dynamic arrays | D5 Example using new ARRAY OF ARRAY construct introduced in D4:
How to create a Bitmap from numeric data? (D5) // Delphi 3 Example of 2-Dimensional Dynamic Array |
C-9. Open Array Parameters; Slice Function |
From the Delphi 3 Object Pascal Language Guide: Open-array parameters allow arrays of varying sizes to be passed to the same procedure or function. A formal parameter declared using the syntax: ARRAY OF T. Within the procedure or function, the formal parameter behaves as if it was declared as ARRAY[0..N - 1] OF T, where N is the number of elements in the actual parameter. Note: When applied to open-array parameters, the Low standard function returns zero, the High standard function returns the index of the last element in the actual array parameter. The Slice function was introduced in Delphi 2. Use Slice for passing variable-sized "open" arrays to certain functions, e.g., mean, sum, SumInt, MaxValue, MaxIntValue, etc. in Borland math unit, or user-written routines. Simple Slice Example: CONST Example defining open array function, dynamic allocation of array, and Slice: // Calculate median intensity of RGB array The above RGBMedian function is called by the following: RowLast := BitmapIn.Scanline[j-1]; An Open Array function called by the above example: FUNCTION MedianInteger (x: ARRAY OF INTEGER): INTEGER; |
C-10. Passing Multidimensional Arrays as Parameters | Borland's TI 1477D |
C-11. How to use array of const | Borland TI 582D |
C-12. Dynamic Arrays? A Class Wrapper for TList | Delphi Informant article, Feb. 1997, pp. 58-65. |
C-13. Linked Lists -- When the Data is Too Dynamic for Arrays | Delphi Informant article, May 1998, pp. 64-67. Source code is www.informant.com/libs/delphi/3x/DI9805RS.ZIP |
C-14. Dynamic array of TPoints to draw a polygon | See Borland's FAQ 919D |
C-15. Initialization of two-dimensional array | CONST A: ARRAY[1..2, 1..3] OF INTEGER = ( (1,2,3), (4,5,6)); Also see: Joselito G. Real UseNet Post about "Initializing n-dimensional array-type constants or static arrays" |
C-16. Pointer Math | Subject: Re: Pointer Math From: Earl F. Glynn Date: Thursday, February 19, 1998 10:09 PM Newsgroups: borland.public.delphi.winapi ... In Delphi 2/3, if p is a pointer, you can always do something like this: p := Pointer(INTEGER(p) + 8); If p were a ^INTEGER before the above statement, it will point to "p+8" afterwards. For Delphi 1, see Borland's - TI 926D "How to do pointer arithmetic in Delphi" - TI 1542D, "A better way to do pointer arithmetic" |
C-17. Numeric Edit Box | The NumEdit component is an edit box that only accepts valid numeric values either from the keyboard or through code. Download from Delphi Super Page: http://delphi.icm.edu.pl/ftp/d10free/numedit.zip |
C-18. Numeric panel | Jean-Yves Qu閕nec's NumPanel demo program. Numpanel is a program sample (not a component) for "mouse only" numeric matrix input. It's very easy to use and simple to code. Two separate zip files contain the program (Numpanel.zip), and the text (Numpaneldoc.zip) in Html format with 3 images. |
Links Verified 12 Nov 2000
Updated 09 Mar 2003
since 1 Nov 1998