Arturo Barreda
Arturo Barreda

Reputation: 43

Objective C vs Swift math operations

Performing the following operation in Objective-C and Swift returns different results:

With an input of 23492.4852,

Objective-C function:

+ (double)funTest:(double)a {
    return a - (int) a / 360 * 360;
}

returns 92.48521

Swift function:

class func funTest(a: Double) -> Double {
    return a - Double(Int(a)) / 360 * 360
}

returns 0.48521

Does anybody know why the difference?

Upvotes: 3

Views: 169

Answers (3)

CRD
CRD

Reputation: 53000

Does anybody know why the difference?

You've just made a simple grouping error.

As you figured out both Objective-C and Swift require a cast when converting from a floating-point value to an integer one, so you have written (int)a for the former and Int(a) for the latter.

You have also understood that converting from an integer to a floating-point value differs in the two languages, in Objective-C (and C and lots of other languages) the conversion is implicit whereas in Swift it is explicit.

The only mistake you have made is in parsing the Objective-C and hence producing the wrong Swift or you've simply mis-typed the Swift.

In arithmetic expressions operators are evaluated according to a priority, relevant to your problem casts bind tightly to the following expression, multiplication and division is done next, then addition and subtraction. What this means is your Objective-C:

a - (int) a / 360 * 360

is parsed as:

a - (double) ( (int) a / 360 * 360 )

note that the (double) cast applies to the result of the expression (int) a / 360 * 360. What you've written in Swift is:

a - Double(Int(a)) / 360 * 360

which isn't the same, here the cast only applies to Int(a). What you should have written is:

a - Double(Int(a) / 360 * 360)

which applies the cast to Int(a) / 360 * 360 just as the Objective-C does.

With that correction in both languages the multiplication and division all operate on integers, and integer division is truncating (e.g. 9 / 4 is 2 not 2.25). With the misplaced parenthesis in Swift the multiplication and division all operate on floating-point values.

TL;DR: You just misplaced a parenthesis.

HTH

Upvotes: 1

Code Different
Code Different

Reputation: 93161

The difference is integer vs. floating point division. In integer division, the fractional part is ignored. Some quick examples are 1 / 2 = 0 or 2 / 3 = 0 but 1.0 / 2.0 = 0.5 and 2.0 / 3.0 = 0.67.

Let's break down how your code works in both languages:

Objective-C

Assuming a = 23492.4852:

a - (int) a / 360 * 360 = a - ((int) a) / 360 * 360
                        = a - 23492 / 360 * 360     // integer division
                        = a - 65 * 360
                        = 23492.4852 - 23400
                        = 92.4852

Objective-C inherits type promotion rules from C, which can be a lot to remember.

Swift

Assuming a = 23492.4852:

a - Double(Int(a)) / 360 * 360 = a - Double(23492) / 360 * 360  // floating point division
                               = a - 65.2556 * 360
                               = a - 23492
                               = 23492.4852 - 23492
                               = 0.4852

In both cases, the compiler has some leeways in interpreting the literal constant of 360: it can be seen an int or double.

  • I don't know the exact internal workings of the ObjC compiler. You just have to be careful when mixing numeric types in C.
  • Swift tries to prevent this confusion by forcing all operands to be of the same data type. Since a is Double, the only way to interpret 360 is that it must also be a Double.

Upvotes: 3

uti0mnia
uti0mnia

Reputation: 394

It's due to how the compilers see the numbers. Notice in swift you had to explicitly cast a into a double after casting it to an Int? The swift compiler sees the entire expression as Doubles so when you do Double(Int(a)) / 360 * 360 you're getting 23492 / 360 * 360 = 65.25555... * 360 = 23492.4852. However, in C/C++/Obj-C etc it sees that 23492 / 360 as an int division giving 23492 / 360 * 360 = 65 * 360 = 23400. And that's where the 90 comes from (from the loss of precision when dividing 2 ints in C.

Upvotes: 0

Related Questions