Reputation: 43
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
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
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:
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.
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
.
a
is Double
, the only way to interpret 360
is that it must also be a Double
.Upvotes: 3
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 Double
s 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 int
s in C.
Upvotes: 0