Reputation: 31283
I have this expression. It's in Objective-C.
CGFloat x1 = self.frame.size.width / 2 + ((self.frame.size.width - self.borderWidth * 2 - self.graduationOffset) / 2) * cos((6 * i) * (M_PI / 180) - (M_PI / 2));
Here are the values for each variable/property. They are all of type CGFloat
.
self.frame.size.width
= 200
self.borderWidth
= 3
self.graduationOffset
= 10
This whole expression is in a loop that executes 60 times. The value of i
starts from 0 and goes up to 60. In the code example above, it was 0.
The value of x1
is 100.
I converted this expression to Swift like this.
let x1 = Double(frame.size.width / 2 + ((frame.size.width - borderWidth * 2 - graduationOffset) / 2)) * cos(Double((6 * i)) * (M_PI / 180) - (M_PI / 2))
Passing the same values for the variables. the result I get is 1.17566092718146e-14.
I tried to break it down and inspect the values separately to figure this out. But that caused only more confusion. Because I got 0 as the final result!
CGFloat a = self.frame.size.width / 2 + ((self.frame.size.width - self.borderWidth * 2 - self.graduationOffset) / 2);
NSLog(@"%f", a); // 192.000000
CGFloat b = cos((6 * i) * (M_PI / 180) - (M_PI / 2));
NSLog(@"%f", b); // 0.000000
CGFloat c = a * b;
NSLog(@"%f", c); // 0.000000
I tried the same in Swift and got different results.
let a = Double(frame.size.width / 2 + ((frame.size.width - borderWidth * 2 - graduationOffset) / 2))
print(a) // 192.0
let b = cos(Double((6 * i)) * (M_PI / 180) - (M_PI / 2))
print(b) // 6.12323399573677e-17
let c = a * b
print(c) // 1.17566092718146e-14
I've been going at this all day but can't figure out all this. I guess the way expressions are evaluated is different between Objective-C and Swift? I'd really appreciate any help.
Upvotes: 0
Views: 114
Reputation: 130092
Let's split your Obj-C code into 3 parts:
CGFloat x1 = frameWidth / 2 + ((frameWidth - borderWidth * 2 - graduationOffset) / 2) * cos((6 * i) * (M_PI / 180) - (M_PI / 2));
CGFloat part1 = frameWidth / 2;
CGFloat part2 = ((frameWidth - borderWidth * 2 - graduationOffset) / 2);
CGFloat part3 = cos((6 * i) * (M_PI / 180) - (M_PI / 2));
Your Obj-C version is then doing result = part1 + (part2 * part3)
(I am sure you know that *
has precedence over +
) while your additional Double(...)
cast in the Swift version converts the expression into result = (part1 + part2) * part3
. Since part3
is 0
for i = 0
, the result is clear.
Upvotes: 2