3

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?

3 Answers 3

3

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.
Sign up to request clarification or add additional context in comments.

Comments

1

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

Comments

0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.