54
votes

I'm trying to build a simple Swift app to calculate VAT (Value Added taxes = 20%).

func taxesFree(number: Int) -> Double {

    var textfield = self.inputTextField.text.toInt()!
    let VAT = 0.2
    var result = textfield * VAT

    return result        
}

For some reason I keep getting

Binary operator * cannot be applied to operands of type Int and Double

on the line

var result = textfield * VAT    
7

7 Answers

59
votes

You should convert one type to the other one so both variable should be the same types:

var result: Double = Double(textfield) * VAT
10
votes

It's because you're trying to multiply an Int (textfield) with a Double (VAT). Because with such an operation you could lose the precision of the double Swift doesn't allow to convert one to the other so you need to explicitly cast the Int to a Double ...

var result = Double(textfield) * VAT
4
votes

The problem here is that the statement given is literally true, because Swift is strongly typed and doesn't coerce implicitly. Just had a similar case myself with "binary operator '-' cannot be applied to operands of type 'Date' and 'Int'".

If you write:

var result = 10 * 0.2

...that's fine, but if you write:

var number = 10
var result = number * 0.2

...that's not fine. This is because untyped explicit values have an appropriate type selected by the compiler, so in fact the first line is taken as being var result = Double(10) * Double(0.2). After all, as a human being you might mean 10 to be floating-point or an integer - you normally wouldn't say which and would expect that to be clear from context. It might be a bit of a pain, but the idea of strong types is that after the code is parsed it can only have one valid compiled expression.

In general you would build a new value using the constructor, so var result = Double(textfield) * VAT in your case. This is different from casting (textfield as Double) because Int is not a subclass of Double; what you are doing instead is asking for a completely new Double value to be built at runtime, losing some accuracy if the value is very high or low. This is what loosely typed languages do implicitly with pretty much all immediate values, at a small but significant time cost.

In your specific case, it wasn't valuable to have an Int in the first place (even if no fraction part is possible) so what you needed was:

func taxesFree(number: Int) -> Double {
    var textfield = Double(self.inputTextField.text)!
    let VAT = 0.2
    var result = textfield * VAT
    return result
}
3
votes

In my case it was just casting to CGFloat:

self.cnsMainFaqsViewHight.constant = CGFloat(self.mainFaqs.count) * 44.0
1
votes

You can convert like var result: Double = Double(textfield)

1
votes

I was misunderstanding the Closed Range Operator in Swift.

You should not wrap the range in an array: [0...10]

for i in [0...10] {
    // error: binary operator '+' cannot be applied to operands of type 'CountableClosedRange<Int>' and 'Int'
    let i = i + 1
}

for i in 0...10 {
    // ok!
    let i = i + 1
}

The range is a collection that can itself be iterated. No need to wrap it in an array, as perhaps you would have in Objective-C.

 0...3  ->  [0, 1, 2, 3]
[0...3] -> [[0, 1, 2, 3]]

Once you realize your object is a nested collection, rather than an array of Ints, it's easy to see why you cannot use numeric operators on the object.

0
votes

This worked for me when I got the same error message in Playground:

func getMilk(howManyCartons: Int){
    print("Buy \(howManyCartons) cartons of milk")
    let priceToPay: Float = Float(howManyCartons) * 2.35
    print("Pay $\(priceToPay)")
}
getMilk(howManyCartons: 2)