Fractions: what changed
Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.
| Old | New | Line | |
|---|---|---|---|
| 1 | 1 | ## What is Fractions? | |
| 2 | 2 | ||
| 3 | 3 | Fractions is a [[Unit|unit]] for doing calculations with fractions.\ | |
| 4 | 4 | The unit was inspired by a [discussion on the Lazarus forum](http://forum.lazarus.freepascal.org/index.php/topic,27805.0.html). | |
| 5 | 5 | ||
| 6 | 6 | ## Subversion | |
| 7 | 7 | ||
| 8 | 8 | You can get a copy of fractions on | |
| 9 | 9 | ||
| 10 | 10 | `svn `[`https://lazarus-ccr.svn.sourceforge.net/svnroot/lazarus-ccr/components/fractions`](https://lazarus-ccr.svn.sourceforge.net/svnroot/lazarus-ccr/components/fractions) | |
| 11 | 11 | ||
| 12 | 12 | Or you can use viewcv to preview the files: | |
| 13 | 13 | ||
| 14 | 14 | [<http://sourceforge.net/p/lazarus-ccr/svn/HEAD/tree/components/fractions/>](http://sourceforge.net/p/lazarus-ccr/svn/HEAD/tree/components/fractions/) | |
| 15 | 15 | ||
| 16 | 16 | ## Features | |
| 17 | 17 | ||
| 18 | 18 | ### The TFraction type | |
| 19 | 19 | ||
| 20 | 20 | TFraction is an "advanced record": a [[Record|record]] with [[Method|methods]] and [[Property|properties]]. | |
| 21 | 21 | ||
| 22 | 22 | #### Porperties of TFraction | |
| 23 | 23 | ||
| 24 | 24 | - property Numerator: [[Int64]]; | |
| 25 | 25 | - Gets and sets the Numerator part of the fraction | |
| 26 | 26 | - property Denominator: Int64; | |
| 27 | 27 | - Gets and sets the Denominator part of the fraction. | |
| 28 | 28 | - Trying to assign 0 (zero) to TFraction.Denomiator will raise an EZeroDivide [[Exceptions|exception]] | |
| 29 | 29 | ||
| 30 | 30 | #### Methods of TFraction | |
| 31 | 31 | ||
| 32 | 32 | - [[Procedure|procedure]] Normalize; | |
| 33 | 33 | - Normalizes the fraction by dividing the Numerator and Dominatr by their [[Greatest common divisor|greatest common divisor]], e.g. 10/5 becomes 2/1 | |
| 34 | 34 | - [[Function|function]] ToString: [[String]]; | |
| 35 | 35 | - returns the string representation of the fraction (no normalizaltion is done), e.g. when Numerator = 10 and Denominator = 5, the function returns '10/5' | |
| 36 | 36 | - function Resolve: String; | |
| 37 | - | ||
| 37 | + | - retruns the string representation of the fraction after normalization, e.g. when Numerator = 4 and Denominator = 3, the function returns '1 1/3' | |
| 38 | 38 | - function ToFloat: [[Double]]; | |
| 39 | 39 | - returns the floating point representation of the fraction, e.g. when Numerator = 1 and Denominator = 3, the function returns 0.3333333333333 | |
| 40 | 40 | ||
| 41 | 41 | ### Assigning and creating Fractions | |
| 42 | 42 | ||
| 43 | 43 | - function Fraction(ANumerator, ADenominator: Int64): TFraction; | |
| 44 | 44 | - creates the fraction ANumerator/ADenominator, e.g. Fraction(1,2) gives 1/2 (one half). | |
| 45 | 45 | - function Fraction(AIntPart, ANumerator, ADenominator: Int64): TFraction; | |
| 46 | 46 | - creates the fraction ANumerator/ADenominator, e.g. Fraction(1,1,2) gives 1 1/2 (one and one half). | |
| 47 | 47 | ||
| 48 | 48 | ### Supported calculations | |
| 49 | 49 | ||
| 50 | 50 | #### [[Operator overloading|Overloaded]] [[Operator|operators]] | |
| 51 | 51 | ||
| 52 | 52 | - = (equals) | |
| 53 | 53 | - [[Less than|<]] (less than) | |
| 54 | 54 | - [[Greater than|>]] (greater than) | |
| 55 | 55 | - \<= (less than or equal) | |
| 56 | 56 | - \>= (greater than or equal) | |
| 57 | 57 | - [[Becomes|:=]] (assign): this operator allows an Int64 or a String on the right hand side | |
| 58 | 58 | - [[Plus|+]] (add) | |
| 59 | 59 | - [[Minus|-]] (subtract) | |
| 60 | 60 | - [[Asterisk|*]] (multiply): overloaded for fractions and Int64 | |
| 61 | 61 | - [[Slash|/]] (divide): overloaded for fractions and Int64 | |
| 62 | 62 | - ** (power): only allowed for Integers (on right hand side) | |
| 63 | 63 | ||
| 64 | 64 | #### Mathematical functions | |
| 65 | 65 | ||
| 66 | 66 | - function Min(a, b: TFraction): TFraction; [[Inline|inline]]; [[Overload|overload]]; | |
| 67 | 67 | - returns a if (a \<= b), otherwise retruns b | |
| 68 | 68 | - function Max(a, b: TFraction): TFraction; inline; overload; | |
| 69 | 69 | - returns a if (a \>= b), otherwise returns b | |
| 70 | 70 | - function InRange(const AValue, AMin, AMax: TFraction): [[Boolean]]; inline; overload; | |
| 71 | 71 | - returns [[True]] if (AValue \>= AMin) and (AValue \<= AMax), otherwise returns [[False]] | |
| 72 | 72 | - function EnsureRange(const AValue, AMin, AMax: TFraction): TFraction; inline; overload; | |
| 73 | 73 | - returns AMin if (AValue \< AMin), otherwise returns AMax if (AValue \> AMax), otherwise returns AValue | |
| 74 | 74 | - function Sign(const AValue: TFraction): TValueSign; inline; overload; | |
| 75 | 75 | - retruns NegativeValue if (AValue \< 0), otherwise returns PositiveValue if (AValue \>0), otherwise returns ZeroValue | |
| 76 | 76 | - function IsZero(const AValue: TFraction): Boolean; overload; | |
| 77 | 77 | - returns True if (AValue = 0), otherwise returns False | |
| 78 | 78 | - function Abs(const AValue: TFraction): TFraction; overload; | |
| 79 | 79 | - return AValue if (AValue \>= 0), otherwise returns -AValue; | |
| 80 | 80 | ||
| 81 | 81 | ### General purpose functions | |
| 82 | 82 | ||
| 83 | 83 | - function GreatestCommonDivisor(a, b: Int64): Int64; | |
| 84 | 84 | - returns the greates common divisor of a and b | |
| 85 | 85 | - function Floor(D: Double): Int64; overload; | |
| 86 | 86 | - returns the integer part of D (subtracted with 1, if (D \< 0)) | |
| 87 | 87 | ||
| 88 | 88 | ## Conversion routines | |
| 89 | 89 | ||
| 90 | 90 | - function FloatToFraction(Value, Precision: Double): TFraction; | |
| 91 | 91 | - returns an approximation of Value in the form of a fraction, e.g. FloatTofraction(0.5,0.01) returns 1/2 (one half) | |
| 92 | 92 | - Precision defines the acceptable value for which (Abs(Result) - Abs(Value) \<= Precision. | |
| 93 | 93 | - Precision is bound to Value by a magnitude of 15 at most | |
| 94 | 94 | - FloatToFraction in fact is a function varable which is initialized to the MF_FloatTofraction() function. You can assign your own function to it if wanted. | |
| 95 | 95 | - function TryFloatToFraction(Value, Precision: Double; out F: TFraction; AcceptPrecisionError: Boolean): Boolean; | |
| 96 | 96 | - return value depends on AcceptPrecisionError value: | |
| 97 | 97 | - if (AcceptPrecisionError = True) then the function retruns True if an approxiamtion can be found | |
| 98 | 98 | - if (AcceptPrecisionError = False) the functions returns True if an approximation can be found AND Abs(Abs(Result)-Abs(Value)) \<= Precision | |
| 99 | 99 | - the value of F only makes sense if the function returns True | |
| 100 | 100 | - function FloatToFractionDef(Value, Precision: Double; Def: TFraction; AcceptPrecisionError: Boolean): TFraction; | |
| 101 | 101 | - returns the found approximation (F) if TryFloatToFraction(Value, Precision, F, AcceptPrecisionError: Boolean) succeeds, otherwise returns Def | |
| 102 | 102 | - function StrToFraction(const S: String): TFraction; | |
| 103 | 103 | - returns fraction that is represented in S, raises an EConvertError upon failure | |
| 104 | 104 | - function TryStrToFraction(const S: String; out F: TFraction): Boolean; | |
| 105 | 105 | - retruns True if S can be converted to a fraction, otherwise returns False | |
| 106 | 106 | - the value of F only makes sense f the function returns True | |
| 107 | 107 | - function StrToFractionDef(const S: String; Def: TFraction): TFraction; | |
| 108 | 108 | - returns the fraction represented in S if conversion succeeds, otherwise returns Def | |
| 109 | 109 | ||
| 110 | 110 | ## Example program | |
| 111 | 111 | ||
| 112 | 112 | ``` pascal | |
| 113 | 113 | program example; | |
| 114 | 114 | ||
| 115 | 115 | {$mode objfpc}{$H+} | |
| 116 | 116 | {$apptype console} | |
| 117 | 117 | ||
| 118 | 118 | uses | |
| 119 | 119 | Classes, sysutils, fractions, math; | |
| 120 | 120 | ||
| 121 | 121 | var | |
| 122 | 122 | F1, F2: TFraction; | |
| 123 | 123 | D, Prec: Double; | |
| 124 | 124 | i: Integer; | |
| 125 | 125 | begin | |
| 126 | 126 | F1 := Fraction(1,1,3); // 1 1/3 | |
| 127 | 127 | F2 := Fraction(4,3); // 4/3 | |
| 128 | 128 | writeln('F1.ToString = ',F1.ToString); // '4/3' | |
| 129 | 129 | writeln('F1.Resolve = ',F1.Resolve); // '1 1/3' | |
| 130 | 130 | writeln('F1.ToFloat = ',F1.ToFloat:16:16); // 1.3333333333333333 | |
| 131 | 131 | writeln('F2.ToString = ',F2.ToString); // '4/3' | |
| 132 | 132 | writeln('(F1 = F2) = ',F1=F2); //True | |
| 133 | 133 | ||
| 134 | 134 | F1 := Fraction(1,2); | |
| 135 | 135 | F2 := Fraction(1,3); | |
| 136 | 136 | writeln(F1.ToString,' * ',F2.ToString,' = ',(F1*F2).Resolve); // '1/6' | |
| 137 | 137 | writeln(F1.ToString,' / ',F2.ToString,' = ',(F1/F2).Resolve); // '1 1/2' | |
| 138 | 138 | writeln(F1.ToString,' + ',F2.ToString,' = ',(F1+F2).Resolve); // '5/6' | |
| 139 | 139 | writeln(F1.ToString,' - ',F2.ToString,' = ',(F1-F2).Resolve); // '1/6' | |
| 140 | 140 | writeln(F1.ToString,' ** 2 = ',(F1**2).Resolve); // '1/6' | |
| 141 | 141 | ||
| 142 | 142 | D := 0.25; | |
| 143 | 143 | F1 := FloatToFraction(D, 0.000001); | |
| 144 | 144 | writeln('FloatTofraction(0.25) -> ',F1.ToString); // '1/4' | |
| 145 | 145 | writeln; | |
| 146 | 146 | writeln('Approximations of Pi:'); | |
| 147 | 147 | writeln(' [Pi = ',Pi:16:16,']'); | |
| 148 | 148 | Prec := 1.0; | |
| 149 | 149 | for i := 1 to 10 do | |
| 150 | 150 | begin | |
| 151 | 151 | Prec := Prec / 10; | |
| 152 | 152 | F2 := FloatTofraction(Pi, Prec); | |
| 153 | 153 | writeln('FloatTofraction(Pi,',Prec:10:10,') = ',Format('%-13s',[F2.Resolve]),' [',F2.ToFloat:16:16,']'); | |
| 154 | 154 | end; | |
| 155 | 155 | end. | |
| 156 | 156 | ``` | |
| 157 | 157 | ||
| 158 | 158 | This outputs: | |
| 159 | 159 | ||
| 160 | 160 | F1.ToString = 4/3 | |
| 161 | 161 | F1.Resolve = 1 1/3 | |
| 162 | 162 | F1.ToFloat = 1.3333333333333333 | |
| 163 | 163 | F2.ToString = 4/3 | |
| 164 | 164 | (F1 = F2) = TRUE | |
| 165 | 165 | 1/2 * 1/3 = 1/6 | |
| 166 | 166 | 1/2 / 1/3 = 1 1/2 | |
| 167 | 167 | 1/2 + 1/3 = 5/6 | |
| 168 | 168 | 1/2 - 1/3 = 1/6 | |
| 169 | 169 | 1/2 ** 2 = 1/4 | |
| 170 | 170 | FloatTofraction(0.25) -> 1/4 | |
| 171 | 171 | ||
| 172 | 172 | Approximations of Pi: | |
| 173 | 173 | [Pi = 3.1415926535897932] | |
| 174 | 174 | FloatTofraction(Pi,0.1000000000) = 3 1/7 [3.1428571428571428] | |
| 175 | 175 | FloatTofraction(Pi,0.0100000000) = 3 1/7 [3.1428571428571428] | |
| 176 | 176 | FloatTofraction(Pi,0.0010000000) = 3 16/113 [3.1415929203539825] | |
| 177 | 177 | FloatTofraction(Pi,0.0001000000) = 3 16/113 [3.1415929203539825] | |
| 178 | 178 | FloatTofraction(Pi,0.0000100000) = 3 16/113 [3.1415929203539825] | |
| 179 | 179 | FloatTofraction(Pi,0.0000010000) = 3 16/113 [3.1415929203539825] | |
| 180 | 180 | FloatTofraction(Pi,0.0000001000) = 3 4703/33215 [3.1415926539214212] | |
| 181 | 181 | FloatTofraction(Pi,0.0000000100) = 3 4703/33215 [3.1415926539214212] | |
| 182 | 182 | FloatTofraction(Pi,0.0000000010) = 3 4703/33215 [3.1415926539214212] | |
| 183 | 183 | FloatTofraction(Pi,0.0000000001) = 3 14093/99532 [3.1415926536189365] | |
| 184 | 184 | ||
| 185 | 185 | --- | |
| 186 | 186 | *From the Free Pascal wiki, page "Fractions", as it stood on 2022-08-06 after a change by Kai Burghardt, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).* |
