Please note, this blog entry is from a previous course. You might want to check out the current one.

Add the following operations to your Calculator:

a. sin: calculates the sine of the top operand on the stack

b. cos: calculates the cosine of the top operand on the stack

c. π: calculates (well, conjures up) the value of π. For example, 3 π × should put three times the value of π into the display on your calculator. Ditto 3 ↲ π x and also π 3 ×.

Change the empty labels of the three buttons on the right hand side to “sin”, “cos” and “pi”:

Link those buttons to the *operate* method of the view-controller class.

For sinus and cosinus, we just add them as unary operations to the initializer of the calculator-brain class:

[swift]

init() {

…

learnOp(Op.UnaryOperation("sin", sin))

learnOp(Op.UnaryOperation("cos", cos))

}

[/swift]

For pi add a new nullary operation (an function needing no input) to the *Op* structure, having no input and only an return value:

[swift]

private enum Op: Printable

{

…

case NullaryOperation(String, () -> Double)

…

var description: String {

get {

switch self {

…

case .NullaryOperation(let symbol, _):

return symbol

…

}

}

}

}

[/swift]

For the evaluation of the nullary operation, return the result of the operation and the remaining *opStack*:

[swift]

private func evaluate(ops: [Op]) -> (result: Double?, remainingOps: [Op]) {

…

case .NullaryOperation(_, let operation):

return (operation(), remainingOps)

…

}

[/swift]

Finally add pi to the class initializer, using a function not using inputs and returning the value of pi:

[swift]

init() {

…

learnOp(Op.NullaryOperation("π", { M_PI }))

}

[/swift]

The complete code for the task #3 is available on GitHub.

Dear Martin,

nice coding. I’m very happy to see other solutions to this course as well.

But if You let sin and cos to be calculated, the result is in Radian. To get the result in degrees You should multiply your operand with (M_PI / 180.0).

keep going 🙂

I disagree, it’s the operand not the result which is in radiant. The result of sinus and cosinus is always between -1 and +1 … and as scientists and engineers we do prefer radiant over degrees 😉

I’m taking the course on iTunesU, so I find this blog to be incredibly valuable, particularly the decimal task – I could get the decimal appended but I couldn’t figure out how to get the input to be ignored if there was already a decimal. Your solution was helpful. 🙂

I did all of this task way differently, and it seems to work correctly. Am I missing something?

For sin and cos I just added to the switch that was created during the lectures and called the single-argument version of the performOperation function:

case “sin”: performOperation { sin($0) }

case “cos”: performOperation { cos($0) }

For Pi I just created a new function to append constants to the array. It assumes that if the user was in the middle of typing a number, that number should first be added to the array (by pressing enter), and then the display label’s text changed to a string of M_PI and that number is then added to the array.

@IBAction func appendConstant(sender: UIButton) {

enter()

displayLabel.text! = “\(M_PI)”

enter()

}

Is there something in either of these that I’m just not doing it right? As I mentioned, they both SEEMED to work, but I could just be missing something.

I should note, I guess once I go to add more constants I’ll need to do another switch, but with the single Pi constant, it’s OK for now.

Do you see anything odd about coding it this way?

@IBAction func operate(sender:UIButton)

{

let operation = sender.currentTitle!

if userIsInTheMiddleOfTypingANumber

{

if operation == “π”

{

performBinaryOperation

{

$0 * $1

}

}

enter()

}

switch operation

{

…

case “π”:

performPiOperation()

case “sin”:

performUnaryOperation

{

sinh($0)

}

case “cos”:

performUnaryOperation

{

cosh($0)

}

default:

break

}

}

func performBinaryOperation(operation:(Double, Double) -> Double)

{

if operandStack.count >= 2

{

displayValue = operation(operandStack.removeLast(), operandStack.removeLast())

enter()

}

}

func performUnaryOperation(operation:Double -> Double)

{

if operandStack.count >= 1

{

displayValue = operation(operandStack.removeLast())

enter()

}

}

func performPiOperation()

{

display.text = “\(M_PI)”

operandStack.append(displayValue)

}

Note: I haven’t implemented the rest of the tasks. This is as of the end of Lecture 2

… that’s not really separating the model from the controller, is it?

No, it’s not .

(Note: This does not reflect that because the separation between the Model and the Controller is part of Programming Project 2.)

I was refering to the implementation of Assignment I: Task # 3.

In assignment #2 task #7 we are asked to provide a human readable description of the elements stored in the calculator brain. Especially item (g) that when you enter

pifollowed bycosit should displaycos(π). That would be difficult if you store the value ofpionly.How does this look? It seems to work as expected.

// MARK: Perform PI

@IBAction func performPI(sender: UIButton) {

if userIsInTheMiddleOfTypingANumber {

enter()

display.text = “\(M_PI)”

enter()

} else {

display.text = “\(M_PI)”

enter()

}

}

if it works for you, it’s perfect!