Math with fractions?

M

Matt R.

I'm taking a tire size from one side and the other so for instance, someone
would type in "29 13/16" to represent "twenty-nine inches and thirteen
sixteenths" for the left side and on the other side it would be the same
situation but a different measurement. "32 9/16" to represent "thirty-two
inches and nine sixteenths."

Now with two text boxes populated as:
LFsize = "29 13/16"
RFsize = "32 9/16"

How in the heck do I calculate this to determine the difference and
represent it in fraction format?

Don't say you have to convert the output to decimal because I am trying to
mimick a grossly expensive program and it does this exact thing using
"FileMaker Pro" by cheezy programmers. I am an ASP.NET C# programmer and
never ran across this need before.

Can anybody offer any help? I believe I have to take the input as a string
format and delimit that string into separate integers or such and do the
math, but within VBA I'm lost!
 
J

Jeff Boyce

Matt

What you are asking for may not be "built-in" in Access. If you have
experience with ASP.Net & C#, I would guess you understand the need for
custom procedures.

Have you tried searching on-line with such keywords as "calculating with
fractions"? Perhaps others have already built such custom procedures...

Or maybe Excel offers such a function ... if so, you could reference the
Excel Object Model and "use" that function.

Good luck

Regards

Jeff Boyce
Microsoft Office/Access MVP
 
M

Matt R.

Jeff,

Yes, I had to create a custom function. The text has to be entered as a
string type and broken down into an array of numbers. What I was after was
some type of example and the math of which I was looking for would be used as
below.

a/b + c/d = (ad + bc) / bd
-and-
a/b - c/d = (ad - bc) / bd

Anyway, thanks for the help! I figured it out.

Hmm.... Now if only I can simply convert decimal out put of this math to a
fraction. Grrrr.

I knew I had to create a custom function but the thought I was having was
for one why the heck aren't fractions native to Microsoft's business
applications that we use in so many different environments? I guess it's
good they offer VBA capabilities.

Anyway, what I say doesn't matter because no matter who says what, Microsoft
is too big and heartless to listen to their customers.

Thanks Jeff!!!
 
S

Stefan Hoffmann

hi Matt,
Now with two text boxes populated as:
LFsize = "29 13/16"
RFsize = "32 9/16"
How in the heck do I calculate this to determine the difference and
represent it in fraction format?
I am an ASP.NET C# programmer and never ran across this need before.
Then the solution should be clear: Implement a class doing the parsing
and the basic arithmetics you need, e.g.:

Option Compare Database
Option Explicit

Public Sub Test()

Dim f1 As clsFractional
Dim f2 As clsFractional

Set f1 = New clsFractional
Set f2 = New clsFractional

f1.FromString "29 13/16"
f2.FromString "32 9/16"

MsgBox f1.ToString() & " - " & _
f2.ToString() & " = " & _
f1.Subtract(f2).ToString() & " (" & _
f1.Subtract(f2).ToDouble() & ")"

End Sub

---

Option Compare Database
Option Explicit

Private m_Integer As Long
Private m_Denominator As Long
Private m_Divisor As Long

Public Property Get IntegerValue() As Long

IntegerValue = m_Integer

End Property

Public Property Get DenominatorValue() As Long

DenominatorValue = m_Denominator

End Property

Public Property Get DivisorValue() As Long

DivisorValue = m_Divisor

End Property

Public Property Let IntegerValue(AValue As Long)

m_Integer = AValue

End Property

Public Property Let DenominatorValue(AValue As Long)

m_Denominator = AValue

End Property

Public Property Let DivisorValue(AValue As Long)

m_Divisor = AValue

End Property

Public Sub FromString(AValue As String)
' Needs correct handling of all possible values.
' This is just the trival parser.

Dim Slash As Long
Dim Space As Long

Slash = InStr(AValue, "/")
Space = InStr(AValue, " ")

m_Integer = CLng(Mid(AValue, 1, Space - 1))
m_Denominator = CLng(Mid(AValue, Space + 1, Slash - Space - 1))
m_Divisor = CLng(Mid(AValue, Slash + 1))

Debug.Print m_Integer; m_Denominator; m_Divisor

End Sub

Public Sub NormalizeFraction()

If Abs(m_Denominator) > m_Divisor Then

m_Integer = Sgn(m_Denominator) * _
(m_Integer + Abs(m_Denominator) \ m_Divisor)
m_Denominator = Abs(m_Denominator) - _
(Abs(m_Denominator) \ m_Divisor) * m_Divisor

End If

End Sub

Public Function Subtract(AValue As clsFractional) As clsFractional
' Trival case, assume same divisor.

Dim Result As clsFractional

Set Result = New clsFractional

Result.DenominatorValue = _
(IntegerValue * DivisorValue + DenominatorValue) - _
(AValue.IntegerValue * AValue.DivisorValue + AValue.DenominatorValue)
Result.DivisorValue = DivisorValue

Set Subtract = Result

End Function

Public Function ToDouble() As Double

Dim Result As Double

Result = m_Integer + m_Denominator / m_Divisor

ToDouble = Result

End Function

Public Function ToString() As String

Dim Result As String

NormalizeFraction
Result = m_Integer & " " & m_Denominator & "/" & m_Divisor

ToString = Result

End Function


If you use this, I strongly encourage you to post your final implementation.

mfG
--> stefan <--
 
M

Matt R.

Stefan,

I am sure I will eventually implement your solution as mine is quite a bit
messy but I have come up with a very crude but working alternative:

Public Function DecimalToFraction(x)
Dim Temp As String
Dim Fixed As Double

If (VarType(x) < 2) Or (VarType(x) > 6) Then
DecimalToFraction = x
Else
x = Abs(x)
Fixed = Int(x)
If Fixed > 0 Then
Temp = Str(Fixed)
End If
Select Case x - Fixed
Case Is < 0.007813
If Fixed > 0 Then
Temp = Temp
Else
Temp = Str(x)
End If
Case 0.007813 To 0.023438
Temp = Temp + " 1/64"
Case 0.023438 To 0.039063
Temp = Temp + " 1/32"
Case 0.039063 To 0.054688
Temp = Temp + " 3/64"
Case 0.054688 To 0.070313
Temp = Temp + " 1/16"
Case 0.070313 To 0.085938
Temp = Temp + " 5/64"
Case 0.085938 To 0.101563
Temp = Temp + " 3/32"
Case 0.101563 To 0.117188
Temp = Temp + " 7/64"
Case 0.117188 To 0.132813
Temp = Temp + " 1/8"
Case 0.132813 To 0.148438
Temp = Temp + " 9/64"
Case 0.148438 To 0.164063
Temp = Temp + " 5/32"
Case 0.164063 To 0.179688
Temp = Temp + " 11/64"
Case 0.179688 To 0.195313
Temp = Temp + " 3/16"
Case 0.195313 To 0.210938
Temp = Temp + " 13/64"
Case 0.210938 To 0.226563
Temp = Temp + " 7/32"
Case 0.226563 To 0.242188
Temp = Temp + " 15/64"
Case 0.242188 To 0.257813
Temp = Temp + " 1/4"
Case 0.257813 To 0.273438
Temp = Temp + " 17/64"
Case 0.273438 To 0.289063
Temp = Temp + " 9/32"
Case 0.289063 To 0.304688
Temp = Temp + " 19/64"
Case 0.304688 To 0.320313
Temp = Temp + " 5/16"
Case 0.320313 To 0.335938
Temp = Temp + " 21/64"
Case 0.335938 To 0.351563
Temp = Temp + " 11/32"
Case 0.351563 To 0.367188
Temp = Temp + " 23/64"
Case 0.367188 To 0.382813
Temp = Temp + " 3/8"
Case 0.382813 To 0.398438
Temp = Temp + " 25/64"
Case 0.398438 To 0.414063
Temp = Temp + " 13/32"
Case 0.414063 To 0.429688
Temp = Temp + " 27/64"
Case 0.429688 To 0.445313
Temp = Temp + " 7/16"
Case 0.445313 To 0.460938
Temp = Temp + " 29/64"
Case 0.460938 To 0.476563
Temp = Temp + " 15/32"
Case 0.476563 To 0.492188
Temp = Temp + " 31/64"
Case 0.492188 To 0.507813
Temp = Temp + " 1/2"
Case 0.507813 To 0.523438
Temp = Temp + " 33/64"
Case 0.523438 To 0.539063
Temp = Temp + " 17/32"
Case 0.539063 To 0.554688
Temp = Temp + " 35/64"
Case 0.554688 To 0.570313
Temp = Temp + " 9/16"
Case 0.570313 To 0.585938
Temp = Temp + " 37/64"
Case 0.585938 To 0.601563
Temp = Temp + " 19/32"
Case 0.601563 To 0.617188
Temp = Temp + " 39/64"
Case 0.617188 To 0.632813
Temp = Temp + " 5/8"
Case 0.632813 To 0.648438
Temp = Temp + " 41/64"
Case 0.648438 To 0.664063
Temp = Temp + " 21/32"
Case 0.664063 To 0.679688
Temp = Temp + " 43/64"
Case 0.679688 To 0.695313
Temp = Temp + " 11/16"
Case 0.695313 To 0.710938
Temp = Temp + " 45/64"
Case 0.710938 To 0.726563
Temp = Temp + " 23/32"
Case 0.726563 To 0.742188
Temp = Temp + " 47/64"
Case 0.742188 To 0.757813
Temp = Temp + " 3/4"
Case 0.757813 To 0.773438
Temp = Temp + " 49/64"
Case 0.773438 To 0.789063
Temp = Temp + " 25/32"
Case 0.789063 To 0.804688
Temp = Temp + " 51/64"
Case 0.804688 To 0.820313
Temp = Temp + " 13/16"
Case 0.820313 To 0.835938
Temp = Temp + " 53/64"
Case 0.835938 To 0.851563
Temp = Temp + " 27/32"
Case 0.851563 To 0.867188
Temp = Temp + " 55/64"
Case 0.867188 To 0.882813
Temp = Temp + " 7/8"
Case 0.882813 To 0.898438
Temp = Temp + " 57/64"
Case 0.898438 To 0.914063
Temp = Temp + " 29/32"
Case 0.914063 To 0.929688
Temp = Temp + " 59/64"
Case 0.929688 To 0.945313
Temp = Temp + " 15/16"
Case 0.945313 To 0.960938
Temp = Temp + " 61/64"
Case 0.960938 To 0.976563
Temp = Temp + " 31/32"
Case 0.976563 To 0.992188
Temp = Temp + " 63/64"
Case Is > 0.992188
Temp = Str(Int(x) + 1)
End Select

DecimalToFraction = Temp

End If
End Function

Public Function CalcMixedFraction(strMixed As String) As Single
On Error Resume Next
Dim i As Integer

' Declare undimensioned array.
' The Split function will dynamically scope it to 2 elements.
Dim strMyArray() As String

CalcMixedFraction = 0

' This code assumes a hyphen delimiter. If the field contains only a whole
part,
' it will calculate correctly, but if the user enters a whole part, a
space, and the
' fractional part, the function will calculate zero. My preference would
be to use
' the textbox's BeforeUpdate event to ensure the value is in the proper
' format however, if you wish to permit either a hyphen or a space
' delimiter, include the optional code below in your function.

strMyArray = Split(strMixed, "-")
For i = 0 To UBound(strMyArray)
CalcMixedFraction = CalcMixedFraction + Eval(strMyArray(i))
Next i

' Optional code to permit space delimiter
If CalcMixedFraction = 0 Then
strMyArray = Split(strMixed, " ")
For i = 0 To UBound(strMyArray)
CalcMixedFraction = CalcMixedFraction + Eval(strMyArray(i))
Next i
End If
End Function
 
S

Stefan Hoffmann

hi Matt,
I am sure I will eventually implement your solution as mine is quite a bit
messy but I have come up with a very crude but working alternative:
It's not necessarily messy. The CalcMixedFraction() function is that
what I called "parser". Then the only thing left is: do you want to do
exact math or not?

If you need exact results than you need to implement a class doing
correct fractional math otherwise you can use your idea.
Public Function DecimalToFraction(x)
End Function
Instead of hardcoding, I would use a function like

http://www.vbforums.com/showthread.php?t=454569
http://www.ozgrid.com/forum/showthread.php?t=22530


mfG
--> stefan <--
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top