Swift-Binary operator cannot be applied to two "Double" operands [duplicate] - swift

This question already has answers here:
binary operator '/' cannot be applied to two 'Double' operands
(3 answers)
Closed 6 years ago.
I'm receiving what appears to be a relatively common error in my code, but examples of solutions to it on other questions didn't appear to be quite relevant to my situation. For example; (binary operator '/' cannot be applied to two 'Double' operands)
let variable1 = Double()
let variable2 = Double()
let array = [5, 10]
var variable3 = Double()
func function() {
let variable1 = 50 / variable2
let variable3 = Double(arc4random_uniform(UInt32(Double(array.count))))
let scaleAction = SKAction.scale(by: variable1 * variable3, duration: 1)
That's all the relevant code anyway. For whatever reason I receive an error, focused on the multiplication star in the last line, saying that the "Binary operator "*" cannot be applied to two "Double" operands. Why can't it? And is there a way I can fix this?
Thanks in advance.

The error message is a bit misleading. The real problem is that scale(by:duration:) takes a CGFloat as the scale:
open class func scale(by scale: CGFloat, duration sec: TimeInterval) -> SKAction
So, you need to pass a CGFloat. You can either work to make sure variable1 and variable3 are CGFloats, or you can use the CGFloat constructor to convert it from a Double:
let scaleAction = SKAction.scale(by: CGFloat(variable1 * variable3), duration: 1)

Related

do we need to explicitly case type when converting? [duplicate]

This question already has answers here:
How does Swift's int literal to float inference work?
(3 answers)
Closed 4 years ago.
when I read the doc of swift
https://docs.swift.org/swift-book/LanguageGuide/TheBasics.html
let anotherPi = 3 + 0.14159
// anotherPi is also inferred to be of type Double
this works, however if I delete the "Double" in the following case, it does not work.
let three = 3
let pointOneFourOneFiveNine = 0.14159
let pi = Double(three) + pointOneFourOneFiveNine
May I ask why do we need to explicitly convert the type in second case? what is the difference?
It is because of Swift's automatic type inference.
let three = 3 // Here **three** is inferred as Int
let pointOneFourOneFiveNine = 0.14159 // Here **pointOneFourOneFiveNine** is inferred as Double
let pi = Double(three) + pointOneFourOneFiveNine
And since you cannot add a Double to an Int, it’s the reason that you have to wrap the three as Double(three).
let anotherPi = 3 + 0.14159
// anotherPi is also inferred to be of type Double
The reason the above code works because the compiler finds that both the summing inputs can be represented as Double, so it assigns the type Double to anotherPi. Hope this clears your doubt.

CGFloat variable returns 0.0 [duplicate]

This question already has an answer here:
Strange Swift numbers type casting
(1 answer)
Closed 5 years ago.
When I try this:
let progress: CGFloat = CGFloat(2 / 3)
print(progress)
The console returns 0 but the result is 0,66666666667, not 0.... Why is that happening?
When I try:
let progress: CGFloat = CGFloat(10 / 3)
print(progress)
It returns 3.0, is that the way how CGFloat works? Is there no way to get comma numbers with CGFLoat?
If you leave out converting, this will work perfectly.
let progress: CGFloat = 2 / 3
print(progress) //0.666666666666667
The reason why this does not work with explicit converting is beause Swift treats a whole number as an Int if it's without context.
That's exactly what is happening inside converting brackets.

How to convert Swift 3 output of readLine() to Integer?

Please don't mark as duplicate until you read the whole thing. This is specific to Swift 3.
I have functions that have parameters such as Ints, Floats, etc. I'd like to take the output of readLine() and have Swift accept the output of readLine() as these types, but unfortunately readLine() outputs a String? and when I try to convert it tells me it's not unwrapped. I need help. I'm using Ubuntu 16.04.
For example, if I had area(width: 15, height: 15), how would I replace 15 and 15 with two constants containing readLine() or any equivalent to readLine() to accept input from a user in the terminal?
Also note that the program I am writing is specifically doing math, as most people seem to be happy with strings, this is literally a CLI-based calculator.
EDIT 1 (lol) Okay, here's a more exact explanation of above. The following code will print the area of a trapezoid:
import Foundation
func areaTrapezoid(height: Float, baseOne: Float, baseTwo: Float) {
let inside = baseOne + baseTwo
let outside = 0.5 * height
let result = outside * inside
print("Area of Trapezoid is \(result)")
}
areaTrapezoid(height: 10, baseOne: 2, baseTwo: 3)
So, the trapezoid has a height of 10 units, and two bases that have lengths of 2 and 3 respectively. However, I want to do something like:
import Foundation
func areaTrapezoid(height: Float, baseOne: Float, baseTwo: Float) {
let inside = baseOne + baseTwo
let outside = 0.5 * height
let result = outside * inside
print("Area of Trapezoid is \(result)")
}
let h = readLine()
areaTrapezoid(height: h, baseOne: 2, baseTwo: 3)
Except, as is already obvious, readLine() will output an optional string, and not a Float. I want the user to be able to input the numbers via CLI in sort of an interactive way, if you will. I'm just learning Swift, but I did something similar in C++ when I was learning that language. Thanks for any help you can provide.
readLine() returns an Optional String.
To unwrap the String, you can use if let, and to convert the String to an integer, use Int().
Example:
import Foundation
if let typed = readLine() {
if let num = Int(typed) {
print(num)
}
}
Let's say you prompted the user twice:
let prompt1 = readLine()
let prompt2 = readLine()
Then:
if let response1 = prompt1,
response2 = prompt2,
num1 = Int(response1),
num2 = Int(response2) {
print("The sum of \(num1) and \(num2) is \(num1 + num2)")
}

Difference between : and = [duplicate]

This question already has answers here:
What is the difference between ":" and "=" in Swift?
(3 answers)
Closed 7 years ago.
I have been programming in Swift for quite a while. But still I haven't got down the whole of the basics and haven't understood the difference between '=' and ':'. We use these to declare variables. But what is the difference between equal to and a colon while programming in Swift? Any help will be appreciated!
With : you are declaring a type and with = you are assigning a value.
Check out the section "Type Annotations" in the Apple Swift guide.
In response to the comment:
when we use = also while declaring the type. For example- var anyVariable = Int. In this we are declaring the type, isn't it? Pardon me if I am wrong. – ojassethi
This is because the type will automatically recognized.
For example all Strings are declared with quotation marks
let myString = "Hello" // The right Value is a String, so the variable is of the type string
While on the other hand it could mistake a value if you are not precisely using =
let myDouble = 1 // myDouble is an Int! not a Double, because for the compiler 1 is an Int
let myDouble: Double = 1 // Now myDouble is a Double
let myDouble = 1.0 // Now myDouble also is a Double

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

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
You should convert one type to the other one so both variable should be the same types:
var result: Double = Double(textfield) * VAT
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
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
}
In my case it was just casting to CGFloat:
self.cnsMainFaqsViewHight.constant = CGFloat(self.mainFaqs.count) * 44.0
You can convert like
var result: Double = Double(textfield)
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.
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)