Задание 2

94 views
Skip to first unread message

Александр

unread,
Mar 12, 2015, 2:31:38 PM3/12/15
to swi...@googlegroups.com
Здравствуйте! Хочу узнать правильно ли я понял задание номер 2 пункта 5, а именно. 
  1. Добавьте способности вашему CalculatorBrain помещать “переменные” в его внутренний стэк. Сделайте это путем реализации следующего API в вашем CalculatorBrain ... 

 Это то есть калькулятор должен воспринимать, первое число например 57 как переменную x, а второе число 21 как переменную y и уже с переменными производятся вычисления? 

Алексей Ракеев

unread,
Mar 12, 2015, 4:42:11 PM3/12/15
to swi...@googlegroups.com
Не выдумывайте, числа должны обрабатываться как числа. В дополнение к ним должна быть возможность вставить в качестве операнда строку.
Для представления переменных в enum Op добавляете еще один case + заводите переменную класса типа Dictionary<String, Double> для хранения значений переменных.
При выводе в поле history используется имя переменной (х, у, М), при вычислении - соответствующее ей значение из этого dictionary (variableValues["M"] и т.д.)
Некоторая аналогия с вставкой числа пи, но с возможностью переназначить соответствующее значение.

Александр

unread,
Mar 12, 2015, 5:04:42 PM3/12/15
to swi...@googlegroups.com
Спасибо за помощь!

Erbol Gabdullin

unread,
Mar 19, 2015, 1:53:57 PM3/19/15
to swi...@googlegroups.com
Из второго задания задача

Задача поставлена так : прочитать стек до конца и записать все что в нем есть в правильной нотации

В общем случае стек может содержать несколько законченных выражений

Например, 2,2,+,2,2,+,2,2,+

В этом случае на выходе должно получиться , 2+2,2+2,2+2

Достаточно разобраться с обработкой одного выражения, а остальные два будут обработаны аналогично, так как функция evaluate возвращает остаток стека и можно видеть что обработка не закончена и перейти к созданию следующей строки

Функция evaluate рекурсивно вызывает себя в случае если элемент стека операция

Если элемент стека операнд, то происходит возврат результата вверх по цепочке функций

Для того чтобы правильно расставить скобки в выражении для бинарной операции нужно иметь информацию о приоритете последней выполненной над операндом операции, для этого нужно немного расширить свойства типа заданного enum Op

Нужно добавить параметр для задания приоритета операции целого типа

Например так

    private enum Op : Printable{
        case Operand(Double)
        case UnaryOperation(String, Int, Double->Double)
        case BinaryOperation(String, Int, (Double,Double)->Double)
        case Variable(String)
        
        var description:String{
            get{
                switch self{
                case .Operand(let operand):
                    return "\(operand)"
                case .Variable(let symbol):
                    return symbol
                case .UnaryOperation(let symbol, _, _):
                    return symbol
                case .BinaryOperation(let symbol, _, _):
                    return symbol
                }
            }
        }
    }

Тогда для получения нужной информации evaluate можно записать так

    private func erbol(ops: [Op])  -> (result: Double?, remainingOps: [Op], pt:Int, di:String){
        if !ops.isEmpty {
            var remainingOps = ops
            let op = remainingOps.removeLast()
            switch op{
            case .Operand(let operand):
                return(operand,remainingOps, 255, "\(operand)")
            case .Variable(let symbol):
                // Ищем значение переменной в словаре
                if let variableValue = variableValues[symbol] {
                    return (variableValue, remainingOps, 255, "")
                } else {
                    // Если значения нет то возвращаем nil
                    return (nil, remainingOps, 255, "")
                }

            case .UnaryOperation(let symbolOperation, let priority, let operation):
                let operandEvaluation = erbol(remainingOps)
                if let operand = operandEvaluation.result{
                    let dis = symbolOperation + "(" + operandEvaluation.di + ")"
                    return (operation(operand), operandEvaluation.remainingOps, priority, dis)
                }
            case .BinaryOperation(let symbolOperation, let priority, let operation):
                var op1Evaluation = erbol(remainingOps)
                if let operand1 = op1Evaluation.result{
                    var op2Evaluation = erbol(op1Evaluation.remainingOps)
                    if let operand2 = op2Evaluation.result{
                        

                        if (priority > op1Evaluation.pt){ op1Evaluation.di = "("  + op1Evaluation.di + ")"}
                        
                        if (priority > op2Evaluation.pt){ op2Evaluation.di = "("  + op2Evaluation.di + ")"}
                        
                        let dis =  op2Evaluation.di + symbolOperation + op1Evaluation.di

                        return (operation(operand1,operand2),op2Evaluation.remainingOps, priority, dis)
                    }
                }
            }
        }
        
        
        return (nil, ops, 255, "")
    }
    
    func erbol1() {
        let aa = erbol(opStack)
        println("Дисплей " + aa.di)

        
    }

Параметр di возвращает созданную строчку с содержимым стека 

Erbol Gabdullin

unread,
Mar 27, 2015, 1:51:05 PM3/27/15
to swi...@googlegroups.com
Относительно величины displayResult

Схема взаимодействия между контроллером и моделью

1. Взаимодействие идет 

(Не будем рассматривать сейчас передачу символа и значения переменной в стек модели. Это не нужно для обсуждения)

через методы модели  
pushOperand и performOperation 

через методы контроллера 
enter() и operate(sender: UIButton). 

В обоих случаях в модель посылаем строку, а получаем обратно с помощью функции evaluate() число типа Double

Переданное число помещаем в display.text как строку через величину displayValue которая преобразует число в строку

2. Видно что displayValue используется всего три раза

а) Два раза для получения числа из модели. Выполняется преобразование Double -> String

b) Один раз для передачи числа в модель в методе enter(). Выполняется преобразование String -> Double

Наша задача научиться передавать в контроллер не только результаты вычислений стека но и сообщения об ошибках

Хаггерти предлагает ввести в контроллер новую величину displayResult

Не понятно зачем, по моему проще проверить в величине displayValue что полученное значение не nil и передать метке дисплея

Немного изменить код evaluate()
1. Возвращаемое значение String
2. Перед отправкой сообщения в контроллер выбрать одно из двух либо сообщение об ошибке либо результат вычислений

Erbol Gabdullin

unread,
Mar 27, 2015, 2:17:18 PM3/27/15
to swi...@googlegroups.com
Извиняюсь , наврал

Немного изменить код evaluate()
1. Возвращаемое значение String?
Reply all
Reply to author
Forward
0 new messages