Two Problems in Swift - swift

I am new to programming and I am making my first app in xcode. I keep getting these 2 errors with little to no information on them on the internet. They are as follows:
Binary operator '*' cannot be applied to operands type '_' and 'String'"
Binary operator '*' cannot be applied to two 'String' operands.
This is the code I have for it.
#IBAction func Calculate(_ sender: UIButton){
// V_1 = (M_3V_2-M_2V_2)/(M_1-M_3)
var a = CurrentPH.text
var b = TargetPH.text
var c = WaterVolume.text
var d = PHDownn.text
var Answer = b! * c! - a! * c! / d! - b!
Answer = PHOutput.text
}
}

Read about binary operators, they need 2 operands to work with. Such as multiplication.
You cannot apply * (multiplication) on two strings.
The first error says that You cannot multiply [anything] with String and the second that you cannot multiply 2 strings together.
It's not clear from your question what are you trying to do.

Adding to what #DeepBlue is saying, I believe what you are trying to do, is to calculate with the values from text fields and place the answer in a fifth text field, when you press a button.
That would look something like this
#IBAction func Calculate(_ sender: UIButton){
// V_1 = (M_3V_2-M_2V_2)/(M_1-M_3)
let a = Int(CurrentPH.text!)!
let b = Int(TargetPH.text!)!
let c = Int(WaterVolume.text!)!
let d = Int(PHDownn.text!)!
let answer = b * c - a * c / d - b
PHOutput.text = String(answer)
}
}
Since none of the variables are modified, I'm using let instead which makes them constants.
Since converting a String to an Int can fail, for example if you type text into the text fields, it can result in a nil result. To simplify the formula the integer conversion is force unwrapped.

Related

Why does a horizontal line appear in Xcode Playground extension when viewing "Show result"?

I am learning about Swift extensions, and wrote a simple extension to Double in a Playground. Code is below.
extension Double {
func round(to places: Int) -> Double {
let precisionNumber = pow(10, Double(places))
var n = self //self contains the value of the myDouble variable
n = n * precisionNumber
n.round()
n = n / precisionNumber
return n
}
}
var myDouble = 3.14159
myDouble.round(to: 1)
The extension works as planned, however when I press "show result" (the eye icon) in the right column for any line of code in the extension, I see a horizontal line.
Anyone know what this line is supposed to signify? Using Xcode 11.2.1 and Swift 5.
The trouble here is that you have not revealed all of your playground. My guess is that there is more code, where you call your extension again. Perhaps your real code looks something like this:
extension Double {
func round(to places: Int) -> Double {
let precisionNumber = pow(10, Double(places))
var n = self //self contains the value of the myDouble variable
n = n * precisionNumber
n.round()
n = n / precisionNumber
return n
}
}
var myDouble = 3.14159
myDouble.round(to: 1) // once
print(myDouble)
myDouble = myDouble.round(to: 1) // twice; in your case it's probably another value
print(myDouble)
That is a very poor way to write your playground, if your goal is to write and debug your extension, for the very reason you have shown. You have called the extension two times, so what meaningful value can be shown as the "result" of each line of the extension? The playground has to try to show you both "results" from both calls. The only way it can think of to do that is to graph the two results.
That is a downright useful representation, though, when you are deliberately looping or repeating code, because you get at least a sense, through the graph, of how the value changes each time thru the loop.

Expression was too complex to be solved in reasonable time error while adding 4 slider values

I tried to add these 4 slider values, but received this error, how do I solve it? Code:
#IBAction func mathValueChanged(_ sender: UISlider) {
let total = MathCriASlider.value + MathCriBSlider.value + MathCriCValue.value + MathCriDSlider.value
mathValue.text = "/(total)"
}
Frustrating for sure, I'm surprised to see this in more recent versions of Swift. In the past I've just had to break down the expression. e.g.
let A = MathCriASlider.value
let B = MathCriBSlider.value
let C = MathCriCSlider.value
let D = MathCriDSlider.value
let total = A + B + C + D
And you may even need to compute a pair of subtotals if it still complains.
The second line needs fixing, your string interpolation is wrong. Use
mathValue.text = "\(total)" // I changed the slash to a backslash

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)")
}

Elementary Q about Swift (1.2) variables

import Foundation
var x = 17.0
var y = 1.0
var z = 0.5
var isSq : Bool = true
y = ((sqrt(x)) - Int(sqrt(x)))
I am working in Xcode 6.4
Last line produces error: 'could not find an overload for '-' that accepts the supplied arguments'.
Would be nice to understand what is happening here, also is there a function which returns just the decimal part of a double variable - the compliment of Int()?
Many thanks
sqrt(x) has the type Double, and Int(sqrt(x)) has the type
Int. There is no minus operator in Swift that takes a Double as
left operand and an Int as right operand,
and Swift does not implicitly convert between types.
Therefore you have to convert the Int to Double again:
let y = sqrt(x) - Double(Int(sqrt(x)))
You can extract the fractional part also with the fmod() function:
let y = fmod(sqrt(x), 1.0)

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)