10

Trying to do arithmetic in a function that returns `CGFloat, I get an error:

Couldn't find overload for '/' that accepts supplied arguments

func kDCControlDegreesToRadians(x : CGFloat) -> CGFloat
{ 
     return (M_PI * (x) / 180.0) // error is here. 
}

Has anyone else seen this type of issue?

jscs
  • 63,694
  • 13
  • 151
  • 195
Mani
  • 17,549
  • 13
  • 79
  • 100
  • 4
    This is not a duplicate. While the error thrown is the same, the underlying reason here is much more nuanced than a misunderstanding of type safety and type inference. – Cezar Jun 09 '14 at 10:27
  • @Mani, I suggest you try to come up with a different title for your question. As it is, it cause confusion with the alleged duplicate and might get your question closed by people who vote based on the title only. – Cezar Jun 09 '14 at 10:31
  • @Cezar I've edited my title, if you feel this title make confusion, feel free to edit my title. – Mani Jun 09 '14 at 10:36

4 Answers4

17

This is a problem with double to float conversion.

On a 64-bit machine, CGFloat is defined as double and you will compile it without problems because M_PI and x are both doubles.

On a 32-bit machine, CGFloat is a float but M_PI is still a double. Unfortunately, there are no implicit casts in Swift, so you have to cast explicitly:

return (CGFloat(M_PI) * (x) / 180.0)

The type for 180.0 literal is inferred.

In Swift 3

M_PI is deprecated, use CGFloat.pi instead:

return (x * .pi / 180.0)
Sulthan
  • 128,090
  • 22
  • 218
  • 270
  • Still my mind flowing with C and Objective-C, that's problem. I got you. Working fine. Thanks @Sulthan.. – Mani Jun 09 '14 at 10:32
11

In this specific case I have a cute trick to recommend

let π = CGFloat(M_PI)

Unicode everywhere, and π is easy to get to with Opt+P

  • +1 for a use of unicode symbol names that doesn't scare me as much as most do :D (I wonder if you could add it as an extension, as `CGFloat.π` would make it apparent what kind of value it is...) – Matt Gibson Oct 29 '14 at 09:23
1

Its best to abstract away the complexity. First create an extension

extension Double {
    /** Converts the specified value in degrees into radians. */
    func degrees() -> CGFloat {
        return CGFloat(self) * CGFloat(M_PI / 180.0)
    }
}

then use it in your code such as the following example

let angle = 30.0.degrees()
let transform = CGAffineTransformRotate(self.sliderControl.transform, angle);

At first I was reluctant to extend Double because I don't like creating a custom tailored use of the language (from coding horrors found in C++). However, practical experience has shown this to being a way of abstraction natural to the language.

Faisal Memon
  • 2,711
  • 16
  • 30
0

This should fix the error:

func kDCControlDegreesToRadians(x : CGFloat) -> CGFloat
{
    return (CGFloat(M_PI) * (x) / 180.0)
}

The reason the error is occurring is because x is explicitly declared to be a CGFloat, while M_PI has the type CDouble, as seen in the declaration:

var M_PI: CDouble { get } /* pi             */

Because of this, you need to cast M_PI to type CGFloat so it matches the type of x (as I have done in the code above). This way, there is no conflict in operating on different types.

Note that, contrary to what is stated in other answers (and as @Cezar commented), you do not need to explicitly cast 180.0 to the CGFloat type, because it is a literal, and does not have an explicit type, so will automatically be converted to CGFloat without needing a manual cast.

Greg
  • 9,068
  • 6
  • 49
  • 91