I am trying to create a function in Playground using Swift where a calculation is made several times, and then added to the total sum of calculations until the loop is over. Everything seems to be working, except that when I try to sum the every calculation to the last total, it just gives me the value of the calculation. Here is my code:
func Calc(diff: String, hsh: String, sperunit: Float, rate: Float, n: Int16, p: Float, length: Int16) -> Float {
//Divisions per Year
let a: Int16 = length/n
let rem = length - (a*n)
let spl = Calc(diff, hsh: hash, sperunit: sperunit, rate: rate)
for var i = 0; i < Int(a) ; i++ { //also tried for i in i..<a
var result: Float = 0
let h = (spl * Float(n) / pow (p,Float(i))) //This gives me a correct result
result += h //This gives me the same result from h
finalResult = result
}
finalResult = finalResult + (Float(rem) * spl / pow (p,Float(a))) //This line is meant to get the result variable out of the loop and do an extra calculation outside of the loop
print(finalResult)
return finalResult
}
Am I doing something wrong?
Currently your variable result is scoped to the loop and does not exist outside of it. Additionally every run of the loop creates a new result variable, initialized with 0.
What you have to do is move the line var result: Float = 0 in front of the for loop:
var result: Float = 0
for var i = 0; i < Int(a) ; i++ {
let h = (spl * Float(n) / pow (p,Float(i)))
result += h
finalResult = result
}
Additionally you can remove the repeated assignment of finalResult = result and just do it once after the loop is over.
You can probably remove the finalResult completely. Just write
var result: Float = 0
for var i = 0; i < Int(a) ; i++ {
let h = (spl * Float(n) / pow (p,Float(i)))
result += h
}
result += (Float(rem) * spl / pow (p,Float(a)))
print(result)
return result
Related
EDIT: Resolved, I answered the question below.
I am using the following to get metadata for PHAssets:
let data = NSData.init(contentsOf: url!)!
if let imageSource = CGImageSourceCreateWithData(data, nil) {
let metadata = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, nil)! as NSDictionary
}
The metadata dictionary has all the values I am looking for. However a few fields like ShutterSpeedValue, ExposureTime which have fractions get printed as decimals:
ExposureTime = "0.05"
ShutterSpeedValue = "4.321956769055745"
When I look at this data on my Mac's preview app and exiftool, it shows:
ExposureTime = 1/20
ShutterSpeedValue = 1/20
How can I get the correct fraction string instead of the decimal string?
EDIT: I tried simply converting the decimal to a fraction string using this from SO code but this isn't correct:
func rationalApproximation(of x0 : Double, withPrecision eps : Double = 1.0E-6) -> String {
var x = x0
var a = x.rounded(.down)
var (h1, k1, h, k) = (1, 0, Int(a), 1)
while x - a > eps * Double(k) * Double(k) {
x = 1.0/(x - a)
a = x.rounded(.down)
(h1, k1, h, k) = (h, k, h1 + Int(a) * h, k1 + Int(a) * k)
}
return "\(h)/\(k)"
}
As you notice, the decimal value of ShutterSpeedValue printed as 4.321956769055745 isn't even equal to 1/20.
Resolved.
As per
https://www.dpreview.com/forums/post/54376235
ShutterSpeedValue is defined as APEX value, where:
ShutterSpeed = -log2(ExposureTime)
So -log2(1/20) is 4.3219, just as what I observed.
So to get the ShutterSpeedValue, I use the following:
"1/\(ceil(pow(2, Double(4.321956769055745))))"
I tested 3 different photos and 1/20, 1/15 and 1/1919 were all correctly calculated using your formula.
I am trying to take transpose of a 2d array in swift. But I don't know why the swapping is not happening.
The array remains the same after taking transpose. I am working with the following code:
var array_4x4 = [[Int]](count: 4, repeatedValue: [Int](count: 4, repeatedValue: 4))
for i in 0..<4
{
for j in 0..<4
{
let temp = Int(arc4random_uniform((100 + 1)) - 1) + 1
array_4x4[i][j] = temp
}
}
for i in 0..<4
{
for j in 0..<4 // code in this loop is not working
{
let temp = array_4x4[i][j]
array_4x4[i][j] = array_4x4[j][i]
array_4x4[j][i] = temp
}
}
Your nested loop runs over all possible array indices (i, j), which means that
each array element is swapped with the transposed element twice.
For example, when i=1 and j=2, the (1, 2) and the (2, 1) array elements are swapped.
Later, when i=2 and j=1, these elements are swapped back.
As a consequence, the matrix is identical to the original matrix in the end.
The solution is to iterate only over (i, j) pairs with i < j,
i.e. swap only the elements above the diagonal with their
counterpart below the diagonal:
for i in 0..<4 {
for j in (i + 1)..<4 {
let temp = array_4x4[i][j]
array_4x4[i][j] = array_4x4[j][i]
array_4x4[j][i] = temp
}
}
Note that the Swift standard library already has a function to
exchange two values:
for i in 0..<4 {
for j in (i + 1)..<4 {
swap(&array_4x4[i][j], &array_4x4[j][i])
}
}
And just for the sake of completeness:
an alternative solution would be to compute the transposed matrix as
a value, and assign it to the same (or a different) variable:
array_4x4 = (0..<4).map { i in (0..<4).map { j in array_4x4[j][i] } }
Based on #Kametrixom answer, I have made some test application for parallel calculation of sum in an array.
My test application looks like this:
import UIKit
import Metal
class ViewController: UIViewController {
// Data type, has to be the same as in the shader
typealias DataType = CInt
override func viewDidLoad() {
super.viewDidLoad()
let data = (0..<10000000).map{ _ in DataType(200) } // Our data, randomly generated
var start, end : UInt64
var result:DataType = 0
start = mach_absolute_time()
data.withUnsafeBufferPointer { buffer in
for elem in buffer {
result += elem
}
}
end = mach_absolute_time()
print("CPU result: \(result), time: \(Double(end - start) / Double(NSEC_PER_SEC))")
result = 0
start = mach_absolute_time()
result = sumParallel4(data)
end = mach_absolute_time()
print("Metal result: \(result), time: \(Double(end - start) / Double(NSEC_PER_SEC))")
result = 0
start = mach_absolute_time()
result = sumParralel(data)
end = mach_absolute_time()
print("Metal result: \(result), time: \(Double(end - start) / Double(NSEC_PER_SEC))")
result = 0
start = mach_absolute_time()
result = sumParallel3(data)
end = mach_absolute_time()
print("Metal result: \(result), time: \(Double(end - start) / Double(NSEC_PER_SEC))")
}
func sumParralel(data : Array<DataType>) -> DataType {
let count = data.count
let elementsPerSum: Int = Int(sqrt(Double(count)))
let device = MTLCreateSystemDefaultDevice()!
let parsum = device.newDefaultLibrary()!.newFunctionWithName("parsum")!
let pipeline = try! device.newComputePipelineStateWithFunction(parsum)
var dataCount = CUnsignedInt(count)
var elementsPerSumC = CUnsignedInt(elementsPerSum)
let resultsCount = (count + elementsPerSum - 1) / elementsPerSum // Number of individual results = count / elementsPerSum (rounded up)
let dataBuffer = device.newBufferWithBytes(data, length: strideof(DataType) * count, options: []) // Our data in a buffer (copied)
let resultsBuffer = device.newBufferWithLength(strideof(DataType) * resultsCount, options: []) // A buffer for individual results (zero initialized)
let results = UnsafeBufferPointer<DataType>(start: UnsafePointer(resultsBuffer.contents()), count: resultsCount) // Our results in convenient form to compute the actual result later
let queue = device.newCommandQueue()
let cmds = queue.commandBuffer()
let encoder = cmds.computeCommandEncoder()
encoder.setComputePipelineState(pipeline)
encoder.setBuffer(dataBuffer, offset: 0, atIndex: 0)
encoder.setBytes(&dataCount, length: sizeofValue(dataCount), atIndex: 1)
encoder.setBuffer(resultsBuffer, offset: 0, atIndex: 2)
encoder.setBytes(&elementsPerSumC, length: sizeofValue(elementsPerSumC), atIndex: 3)
// We have to calculate the sum `resultCount` times => amount of threadgroups is `resultsCount` / `threadExecutionWidth` (rounded up) because each threadgroup will process `threadExecutionWidth` threads
let threadgroupsPerGrid = MTLSize(width: (resultsCount + pipeline.threadExecutionWidth - 1) / pipeline.threadExecutionWidth, height: 1, depth: 1)
// Here we set that each threadgroup should process `threadExecutionWidth` threads, the only important thing for performance is that this number is a multiple of `threadExecutionWidth` (here 1 times)
let threadsPerThreadgroup = MTLSize(width: pipeline.threadExecutionWidth, height: 1, depth: 1)
encoder.dispatchThreadgroups(threadgroupsPerGrid, threadsPerThreadgroup: threadsPerThreadgroup)
encoder.endEncoding()
var result : DataType = 0
cmds.commit()
cmds.waitUntilCompleted()
for elem in results {
result += elem
}
return result
}
func sumParralel1(data : Array<DataType>) -> UnsafeBufferPointer<DataType> {
let count = data.count
let elementsPerSum: Int = Int(sqrt(Double(count)))
let device = MTLCreateSystemDefaultDevice()!
let parsum = device.newDefaultLibrary()!.newFunctionWithName("parsum")!
let pipeline = try! device.newComputePipelineStateWithFunction(parsum)
var dataCount = CUnsignedInt(count)
var elementsPerSumC = CUnsignedInt(elementsPerSum)
let resultsCount = (count + elementsPerSum - 1) / elementsPerSum // Number of individual results = count / elementsPerSum (rounded up)
let dataBuffer = device.newBufferWithBytes(data, length: strideof(DataType) * count, options: []) // Our data in a buffer (copied)
let resultsBuffer = device.newBufferWithLength(strideof(DataType) * resultsCount, options: []) // A buffer for individual results (zero initialized)
let results = UnsafeBufferPointer<DataType>(start: UnsafePointer(resultsBuffer.contents()), count: resultsCount) // Our results in convenient form to compute the actual result later
let queue = device.newCommandQueue()
let cmds = queue.commandBuffer()
let encoder = cmds.computeCommandEncoder()
encoder.setComputePipelineState(pipeline)
encoder.setBuffer(dataBuffer, offset: 0, atIndex: 0)
encoder.setBytes(&dataCount, length: sizeofValue(dataCount), atIndex: 1)
encoder.setBuffer(resultsBuffer, offset: 0, atIndex: 2)
encoder.setBytes(&elementsPerSumC, length: sizeofValue(elementsPerSumC), atIndex: 3)
// We have to calculate the sum `resultCount` times => amount of threadgroups is `resultsCount` / `threadExecutionWidth` (rounded up) because each threadgroup will process `threadExecutionWidth` threads
let threadgroupsPerGrid = MTLSize(width: (resultsCount + pipeline.threadExecutionWidth - 1) / pipeline.threadExecutionWidth, height: 1, depth: 1)
// Here we set that each threadgroup should process `threadExecutionWidth` threads, the only important thing for performance is that this number is a multiple of `threadExecutionWidth` (here 1 times)
let threadsPerThreadgroup = MTLSize(width: pipeline.threadExecutionWidth, height: 1, depth: 1)
encoder.dispatchThreadgroups(threadgroupsPerGrid, threadsPerThreadgroup: threadsPerThreadgroup)
encoder.endEncoding()
cmds.commit()
cmds.waitUntilCompleted()
return results
}
func sumParallel3(data : Array<DataType>) -> DataType {
var results = sumParralel1(data)
repeat {
results = sumParralel1(Array(results))
} while results.count >= 100
var result : DataType = 0
for elem in results {
result += elem
}
return result
}
func sumParallel4(data : Array<DataType>) -> DataType {
let queue = NSOperationQueue()
queue.maxConcurrentOperationCount = 4
var a0 : DataType = 0
var a1 : DataType = 0
var a2 : DataType = 0
var a3 : DataType = 0
let op0 = NSBlockOperation( block : {
for i in 0..<(data.count/4) {
a0 = a0 + data[i]
}
})
let op1 = NSBlockOperation( block : {
for i in (data.count/4)..<(data.count/2) {
a1 = a1 + data[i]
}
})
let op2 = NSBlockOperation( block : {
for i in (data.count/2)..<(3 * data.count/4) {
a2 = a2 + data[i]
}
})
let op3 = NSBlockOperation( block : {
for i in (3 * data.count/4)..<(data.count) {
a3 = a3 + data[i]
}
})
queue.addOperation(op0)
queue.addOperation(op1)
queue.addOperation(op2)
queue.addOperation(op3)
queue.suspended = false
queue.waitUntilAllOperationsAreFinished()
let aaa: DataType = a0 + a1 + a2 + a3
return aaa
}
}
And I have a shader that looks like this:
kernel void parsum(const device DataType* data [[ buffer(0) ]],
const device uint& dataLength [[ buffer(1) ]],
device DataType* sums [[ buffer(2) ]],
const device uint& elementsPerSum [[ buffer(3) ]],
const uint tgPos [[ threadgroup_position_in_grid ]],
const uint tPerTg [[ threads_per_threadgroup ]],
const uint tPos [[ thread_position_in_threadgroup ]]) {
uint resultIndex = tgPos * tPerTg + tPos; // This is the index of the individual result, this var is unique to this thread
uint dataIndex = resultIndex * elementsPerSum; // Where the summation should begin
uint endIndex = dataIndex + elementsPerSum < dataLength ? dataIndex + elementsPerSum : dataLength; // The index where summation should end
for (; dataIndex < endIndex; dataIndex++)
sums[resultIndex] += data[dataIndex];
}
On my surprise function sumParallel4 is the fastest, which I thought it shouldn't be. I noticed that when I call functions sumParralel and sumParallel3, the first function is always slower even if I change the order of function. (So if I call sumParralel first this is slower, if I call sumParallel3 this is slower.).
Why is this? Why is sumParallel3 not a lot faster than sumParallel ? Why is sumParallel4 the fastest, although it is calculated on CPU?
How can I update my GPU function with posix_memalign ? I know it should work faster because it would have shared memory between GPU and CPU, but I don't know witch array should be allocated this way (data or result) and how can I allocate data with posix_memalign if data is parameter passed in function?
In running these tests on an iPhone 6, I saw the Metal version run between 3x slower and 2x faster than the naive CPU summation. With the modifications I describe below, it was consistently faster.
I found that a lot of the cost in running the Metal version could be attributed not merely to the allocation of the buffers, though that was significant, but also to the first-time creation of the device and compute pipeline state. These are actions you'd normally perform once at application initialization, so it's not entirely fair to include them in the timing.
It should also be noted that if you're running these tests through Xcode with the Metal validation layer and GPU frame capture enabled, that has a significant run-time cost and will skew the results in the CPU's favor.
With those caveats, here's how you might use posix_memalign to allocate memory that can be used to back a MTLBuffer. The trick is to ensure that the memory you request is in fact page-aligned (i.e. its address is a multiple of getpagesize()), which may entail rounding up the amount of memory beyond how much you actually need to store your data:
let dataCount = 1_000_000
let dataSize = dataCount * strideof(DataType)
let pageSize = Int(getpagesize())
let pageCount = (dataSize + (pageSize - 1)) / pageSize
var dataPointer: UnsafeMutablePointer<Void> = nil
posix_memalign(&dataPointer, pageSize, pageCount * pageSize)
let data = UnsafeMutableBufferPointer(start: UnsafeMutablePointer<DataType>(dataPointer),
count: (pageCount * pageSize) / strideof(DataType))
for i in 0..<dataCount {
data[i] = 200
}
This does require making data an UnsafeMutableBufferPointer<DataType>, rather than an [DataType], since Swift's Array allocates its own backing store. You'll also need to pass along the count of data items to operate on, since the count of the mutable buffer pointer has been rounded up to make the buffer page-aligned.
To actually create a MTLBuffer backed with this data, use the newBufferWithBytesNoCopy(_:length:options:deallocator:) API. It's crucial that, once again, the length you provide is a multiple of the page size; otherwise this method returns nil:
let roundedUpDataSize = strideof(DataType) * data.count
let dataBuffer = device.newBufferWithBytesNoCopy(data.baseAddress, length: roundedUpDataSize, options: [], deallocator: nil)
Here, we don't provide a deallocator, but you should free the memory when you're done using it, by passing the baseAddress of the buffer pointer to free().
I am doing some bitwise operations in Swift style, which these codes are originally written in Objective-C/C. I use UnsafeMutablePointer to state the beginning index of memory address and use UnsafeMutableBufferPointer for accessing the element within the scope.
You can access the original Objective-C file Here.
public init(size: Int) {
self.size = size
self.bitsLength = (size + 31) / 32
self.startIdx = UnsafeMutablePointer<Int32>.alloc(bitsLength * sizeof(Int32))
self.bits = UnsafeMutableBufferPointer(start: startIdx, count: bitsLength)
}
/**
* #param from first bit to check
* #return index of first bit that is set, starting from the given index, or size if none are set
* at or beyond its given index
*/
public func nextSet(from: Int) -> Int {
if from >= size { return size }
var bitsOffset = from / 32
var currentBits: Int32 = bits[bitsOffset]
currentBits &= ~((1 << (from & 0x1F)) - 1).to32
while currentBits == 0 {
if ++bitsOffset == bitsLength {
return size
}
currentBits = bits[bitsOffset]
}
let result: Int = bitsOffset * 32 + numberOfTrailingZeros(currentBits).toInt
return result > size ? size : result
}
func numberOfTrailingZeros(i: Int32) -> Int {
var i = i
guard i != 0 else { return 32 }
var n = 31
var y: Int32
y = i << 16
if y != 0 { n = n - 16; i = y }
y = i << 8
if y != 0 { n = n - 8; i = y }
y = i << 4
if y != 0 { n = n - 4; i = y }
y = i << 2
if y != 0 { n = n - 2; i = y }
return n - Int((UInt((i << 1)) >> 31))
}
Testcase:
func testGetNextSet1() {
// Passed
var bits = BitArray(size: 32)
for i in 0..<bits.size {
XCTAssertEqual(32, bits.nextSet(i), "\(i)")
}
// Failed
bits = BitArray(size: 34)
for i in 0..<bits.size {
XCTAssertEqual(34, bits.nextSet(i), "\(i)")
}
}
Can someone guide me why the second testcase fail but the objective-c version pass ?
Edit: As #vacawama mentioned: If you break testGetNextSet into 2 tests, both pass.
Edit2: When I run tests with xctool, and tests which calling BitArray's nextSet() will crash while running.
Objective-C version of numberOfTrailingZeros:
// Ported from OpenJDK Integer.numberOfTrailingZeros implementation
- (int32_t)numberOfTrailingZeros:(int32_t)i {
int32_t y;
if (i == 0) return 32;
int32_t n = 31;
y = i <<16; if (y != 0) { n = n -16; i = y; }
y = i << 8; if (y != 0) { n = n - 8; i = y; }
y = i << 4; if (y != 0) { n = n - 4; i = y; }
y = i << 2; if (y != 0) { n = n - 2; i = y; }
return n - (int32_t)((uint32_t)(i << 1) >> 31);
}
When translating numberOfTrailingZeros, you changed the return value from Int32 to Int. That is fine, but the last line of the function is not operating properly as you translated it.
In numberOfTrailingZeros, replace this:
return n - Int((UInt((i << 1)) >> 31))
With this:
return n - Int(UInt32(bitPattern: i << 1) >> 31)
The cast to UInt32 removes all but the lower 32 bits. Since you were casting to UInt, you weren't removing those bits. It is necessary to use bitPattern to make this happen.
Finally I found out that startIdx just need to be initialized after allocation.
self.startIdx = UnsafeMutablePointer<Int32>.alloc(bitsLength * sizeof(Int32))
self.startIdx.initializeFrom(Array(count: bitsLength, repeatedValue: 0))
Or use calloc with just one line code:
self.startIdx = unsafeBitCast(calloc(bitsLength, sizeof(Int32)), UnsafeMutablePointer<Int32>.self)
Furthermore, I use lazy var to defer the Initialization of UnsafeMutableBufferPointer until the property is first used.
lazy var bits: UnsafeMutableBufferPointer<Int32> = {
return UnsafeMutableBufferPointer<Int32>(start: self.startIdx, count: self.bitsLength)
}()
On the other hand, don't forget to deinit:
deinit {
startIdx.destroy()
startIdx.dealloc(bitsLength * sizeof(Int32))
}
I'm doing a fraction calculator and I'm trying to add 2 fractions when I put in my fractions it just adds my Whole numbers only and nothing else if my fraction is 2 3/4 + 2 3/5 it add the whole numbers and outputs 4
var firstStep = firstDenomInTextField! * firstWholeInTextField! / firstDenomInTextField!
var secondStep = firstStep + firstNumInTextField! / firstDenomInTextField!
var thirdStep = secondDenomInTextField! * secondWholeInTextField! / secondDenomInTextField!
var fourthStep = thirdStep + secondNumInTextField! / secondDenomInTextField!
var calculatedAnswer = (secondStep + fourthStep)
var numerator = Int(calculatedAnswer * 10 * 10)
println(numerator)
answerLabel.hidden = false
answerLabel.text = printSimplifiedFraction(Numerator: numerator)
printSimplifiedFraction Function
func printSimplifiedFraction(Numerator numerator: Int, Denominator denominator: Int = 100) -> String
{
var finalNumerator = numerator;
var finalDenominator = denominator;
var wholeNumbers:Int = numerator / denominator;
var remainder:Int = numerator % denominator;
//println("wholeNumbers = \(wholeNumbers), remainder = \(remainder)");
//println("\(denominator) % \(remainder) = \(denominator % remainder)");
if(remainder > 0)
{
// see if we can simply the fraction part as well
if(denominator % remainder == 0) // no remainder means remainder can be simplified further
{
finalDenominator = denominator / remainder;
finalNumerator = remainder / remainder;
}
else
{
finalNumerator = remainder;
finalDenominator = denominator;
}
}
if(wholeNumbers > 0 && remainder > 0)
{
// prints out whole number and fraction parts
return("Simplified fraction of \(numerator)/\(denominator) = \(wholeNumbers) \(finalNumerator)/\(finalDenominator)");
}
else if (wholeNumbers > 0 && remainder == 0)
{
// prints out whole number only
return("Simplified fraction of \(numerator)/\(denominator) = \(wholeNumbers)");
}
else
{
// prints out fraction part only
return("Simplified fraction of \(numerator)/\(denominator) = \(finalNumerator)/\(finalDenominator)");
}
}
My Question I want to make it so it does not just add the whole numbers but add the whole fraction.
If you need any clarifications or questions please comment them down below
If you are working with fractions, you should use Double instead of Int. Also when multiplying by 10 you should use 10.0 instead. Be careful you are mixing Int(Integers) with Double(fractions). Also when declaring vars as parameters if you omit it will be a constant by default, if you would like to change it you don't need a second var, just add var in front of it when declaring it there).
I think You should restart it from the beginning, Syntax is OK. Don't forget to convert from Int to Double when needed.
I think your math is somewhat of in the code your present. The following code calculates the fraction and returns a string with the result.
...
var wholeTotal = firstWholeInTextField! + secondWholeInTextField!
var numeratorTotal = (firstNumInTextField! * secondDenomInTextField!) + (secondNumInTextField! * firstDenomInTextField!)
let denominatorTotal = firstDenomInTextField! * secondDenomInTextField!
while numeratorTotal > denominatorTotal {
wholeTotal++
numeratorTotal -= denominatorTotal
}
let resultString = simplifiedFractionStringWith(wholeTotal, numerator: numeratorTotal, denominator: denominatorTotal)
answerLabel.text = ("The result is: " + resultString)
func simplifiedFractionStringWith(wholeNumber: Int, numerator: Int, denominator: Int) -> String {
if numerator > 0 {
return ("\(wholeNumber) \(numerator)/\(denominator)")
} else {
return ("\(wholeNumber)")
}
}
That being said I really believe the whole thing is much better solved creating a fraction-struct...
Like I mentioned in my other answer I think the whole thing would be much better solved by creating a struct for your fraction. As I (clearly) have no life, I've put together another example:
struct fraction {
var wholeNumber = 0
var numerator = 0
var denominator = 0
func asString()-> String {
if numerator > 0 {
return ("\(wholeNumber) \(numerator)/\(denominator)")
} else {
return ("\(wholeNumber)")
}
}
func combinedWith(aFraction: fraction) -> fraction {
var wholeTotal = wholeNumber + aFraction.wholeNumber
var numeratorTotal = (numerator * aFraction.denominator) + (aFraction.numerator * denominator)
let denominatorTotal = denominator * aFraction.denominator
while numeratorTotal > denominatorTotal {
wholeTotal++
numeratorTotal -= denominatorTotal
}
let combinedFraction = fraction(wholeNumber: wholeTotal, numerator: numeratorTotal, denominator: denominatorTotal)
return combinedFraction
}
}
Then the code to show the total of two fractions would look something like this (in your app):
let firstFraction = fraction(wholeNumber: firstWholeInTextField!, numerator: firstNumInTextField!, denominator: firstDenomInTextField!)
let secondFraction = fraction(wholeNumber: secondWholeInTextField!, numerator: secondNumInTextField!, denominator: secondDenomInTextField!)
let combinedFraction = firstFraction.combinedWith(secondFraction)
answerLabel.text = ("The result is: " + combinedFraction.asString())