Nando said:
I need to store some information in my database in fractions. And I need to
make some basic operations with it (sum, product).
Example:
2 1/2
3 1/4
4 1/8
5 1/16
Can somebody help me?
This problem is much trickier than it appears. I would start by
breaking up your mixed fractions into separate fields.
IPart Numerator Denominator
2 1 2
3 1 4
4 1 8
5 1 16
M1 = IPart1 + Numerator1 / Denominator1
M2 = IPart2 + Numerator2 / Denominator2
Sum:
(A + B / C) + (D + E / F) = A + D + (BF + CE) / CF
= (ACF + DCF + BF + CE) / CF
Product:
(A + B / C) * (D + E / F) = AD + BD / C + AE / F + BE / CF
= (ADCF + BDF + ACE + BE) / CF
Then you need a table of prime numbers along with a means to obtain the
prime factorization. Note that you only need to check for prime factors
that are less than or equal to the square root of the number. But wait.
After cancelling common prime factors (using the exponents), and using
the Mod and Int functions to obtain the separate pieces for the
resulting mixed fraction you discover a problem. When two numbers that
are relatively prime are divided, is the residue also relatively prime? No.
(2^2 * 5 * 9) / (3 * 7) = 180 / 21 = 8 + 12 / 21.
Therefore you would need to reduce the resulting fraction again.
8 4 7
So, the way to do it is to break the Sum or Product numerator and
denominator into a mixed fraction first, then do the prime factorization
on the resulting fraction.
'Begin Module "Air Code" --------
Type MixedFraction
IPart As Long
FPart As Fraction
End Type
Type Fraction
Numerator As Long
Denominator As Long
End Type
Public Function MixedFractionSum(M1 As MixedFraction, M2 As
MixedFraction) As MixedFraction
Dim dblMax As Double
Dim dblNumerator As Double
Dim dblDenominator As Double
Dim SumFraction As Fraction
dblMax = CDbl(2147483647)
'(ACF + DCF + BF + CE) / CF
'Check for overflow (ignore max negative case)
If Abs(CDbl(M1.IPart) * M1.Denominator * M2.Denominator + ... +
M1.Denominator * M2.Numerator) > dblMax Then ...
dblNumerator = Int(M1.IPart * M1.Denominator * M2.Denominator + ...
dblDenominator = M1.Denominator * M2.Denominator
MixedFractionSum.IPart = Int(dblNumerator / dblDenominator)
SumFraction.Numerator = dblNumerator - dblDenominator *
MixedFractionSum.IPart
SumFraction.Denominator = dblDenominator
MixedFractionSum.FPart = SumFraction
End Function
Public Sub MixedFractionProduct(M1 As MixedFraction, M2 As
MixedFraction)) As MixedFraction
Dim dblMax As Double
Dim dblNumerator As Double
Dim dblDenominator As Double
Dim ProductFraction As Fraction
dblMax = CDbl(2147483647)
'(ADCF + BDF + ACE + BE) / CF
'Check for overflow (ignore max negative case)
If Abs(CDbl(M1.IPart) * M2.IPart * M1.Denominator * M2.Denominator + ...
+ M1.Numerator * M2.Numerator) > dblMax Then ...
dblNumerator = Int(M1.IPart * M1.Denominator * M2.Denominator + ...
dblDenominator = M1.Denominator * M2.Denominator
MixedFractionSum.IPart = Int(dblNumerator / dblDenominator)
dblNumerator = dblNumerator - dblDenominator * MixedFractionSum.IPart
ProductFraction.Numerator = dblNumerator
ProductFraction.Denominator = dblDenominator
MixedFractionSum.FPart = ReduceFraction(MyFraction)
Public Function
ReduceFraction(F1 As Fraction) As Fraction
'Some tricky code that interacts with tblPrimeNumbers
End Function
'End Module "Air Code" --------
'Code behind form:
Dim M1 As MixedFraction
Dim M2 As MixedFraction
Dim MSumResult As MixedFraction
Dim MProductResult As MixedFraction
Dim MFraction As Fraction
M1.IPart = 4
MFraction.Numerator = 1
MFraction.Denominator = 8
M1.FPart = MFraction
M2.IPart = 3
MFraction.Numerator = 1
MFraction.Denominator = 4
M2.FPart = MFraction
MSumResult = MixedFractionSum(M1, M2)
MProductResult = MixedFractionProduct(M1, M2)
MsgBox(MSumResult.IPart)
MsgBox(MSumResult.FPart.Numerator)
MsgBox(MSumResult.FPart.Denominator)
From your example I assumed that the fractions do not have very large
numerators or denominators. Obviously, the overflow provisions are
incomplete. Maybe this example will form the basis for a satisfactory
solution.
James A. Fortune
[email protected]