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

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

Related

How to get the first number after a decimal point of a Double?

I have a Double like this:
339.09965653839
How can I get the first number after the dot?
0 // desired result
I tried to look into similar questions but unfortunately I found only ways to separate a double in two parts also these two Double. I would like to have an Int and then be able to print it as a string.
To get the digit as an Int, you can do a little math:
let someNum = 339.09965653839
let digit = Int((someNum - Double(Int(someNum))) * 10)
And of course it is trivial to display digit in/as a string as needed.
Or, alternatively:
let number = 123.456
// 1234 % 123 = 4
let digit = Int(number * 10) % Int(number)
Convert double to string and fetch the first character after dot.
let value = 339.09965653839
let valueInString = "\(value)".split(separator: ".")
print(valueInString[1].first ?? "")

Convert positive value to negative value in swift

I want to convert a positive value to a negative value, for example:
let a: Int = 10
turn it to -10, my current idea is just use it to multiple -1
a * -1
I'm not sure if this is proper, any idea?
With Swift 5, according to your needs, you can use one of the two following ways in order to convert an integer into its additive inverse.
#1. Using negate() method
Int has a negate() method. negate() has the following declaration:
mutating func negate()
Replaces this value with its additive inverse.
The Playground code samples below show how to use negate() in order to mutate an integer and replace its value with its additive inverse:
var a = 10
a.negate()
print(a) // prints: -10
var a = -10
a.negate()
print(a) // prints: 10
Note that negate() is also available for all types that conform to SignedNumeric protocol.
#2. Using the unary minus operator (-)
The sign of a numeric value can be toggled using a prefixed -, known as the unary minus operator. The Playground code samples below show how to use it:
let a = 10
let b = -a
print(b) // prints: -10
let a = -10
let b = -a
print(b) // prints: 10
Just use - operator.
let negativeA = -a

Round a double down to one decimal place (dropping decimal places)

I want to round a double down to 1 decimal place. For example if I have a double let val = 3.1915 I want to round this down to 3.1. Normal rounding functions will round it to 3.2 but I want to basically just drop the remaining decimal places. What is the best way to do this? Is there a native function for this? I know this is pretty straight forward to do but I want to know what the best way to do this would be where I am not using any kind of workaround or bad practices. This is not a duplicate of other rounding questions because I am not asking about about rounding, I am asking how to drop decimal places.
Similarly, if the value was 3.1215, it would also round to 3.1
Use the function trunc() (which stands for truncate) which will chop away the decimal portion without rounding. Specifically, multiply the Double value by 10, truncate it, then divide by 10 again. Then, to display using 1 decimal place, use String(format:):
let aDouble = 1.15
let truncated = trunc(aDouble * 10) / 10
let string = String(format: "%.1f", truncated
print(string)
(displays "1.1")
or, to process an entire array of sample values:
let floats = stride(from: 1.099, to: 2.0, by: 0.1)
let truncs = floats
.map { trunc($0 * 10) / 10 }
.map { String(format: "%.1f", $0) }
let beforeAndAfter = zip(floats, truncs)
.map { (float: $0.0, truncString: $0.1)}
beforeAndAfter.forEach { print(String(format: "%.3f truncated to 1 place is %#", $0.0, $0.1)) }
Outputs:
1.099 truncated to 1 place is 1.0
1.199 truncated to 1 place is 1.1
1.299 truncated to 1 place is 1.2
1.399 truncated to 1 place is 1.3
1.499 truncated to 1 place is 1.4
1.599 truncated to 1 place is 1.5
1.699 truncated to 1 place is 1.6
1.799 truncated to 1 place is 1.7
1.899 truncated to 1 place is 1.8
1.999 truncated to 1 place is 1.9
By your example I assume you meant you want to Truncate, if so using multiply and casting into Int then Dividing and casting back into Float/Double will do.
Example: 3.1915 -> 3.1
var val = 3.1915
let intVal:Int = Int(val*10)
val = Float(intVal)/10.0
print(val) //3.1
If you want more decimal places simply multiply and divide by 100 or 1000 instead.
Then if for any reason you want to use the round() function there is a overloaded variant that accepts a FloatingPointRoundingRule it will work like:
var val = 3.1915
val*=10 //Determine decimal places
val.round(FloatingPoint.towardZero) // .down is also available which differs in rounding negative numbers.
val*=0.1 //This is a divide by 10
print(val) //3.1
In practical usage I'd suggest making an extension or global function instead of writing this chunk every time. It would look something like:
extension Float {
func trunc(_ decimal:Int) {
var temp = self
let multiplier = powf(10,decimal) //pow() for Double
temp = Float(Int(temp*multiplier))/multiplier //This is actually the first example put into one line
return temp
}
}
And used:
var val = 3.1915
print(val.trunc(1)) //3.1

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)

Increment number in Dictionary

I have a Dictionary [String:AnyObject] which contains some keys and values.
I want to increment a key to which value is of type Double.
I can do it this way:
let nr = dict["number"] as! Double
dict["number"] = nr + 10
But I dont like that way so Im wondering if there is another way
I tried this:
(dict["number"] as! Double) += 10
But that gives me an error:
Binary operator '+=' cannot be applied to operands of type '(Double)' and 'Double'
Why isn't this working?
Following is an alternative. If you want to avoid force unwrapping an optional:
dict["number"] = (dict["number"] ?? 0) + 10
You are close and in fact you can write to a dictionary using +=, the problem is your cast. For example we can do:
var dict = ["number" : 2]
dict["number"]! += 10
and now dict["number"] returns 12. Now this is creating a new value (12) and replacing it into the dictionary, it is just a clean way of looking at it.
The problem with your code is that the left side (dict["number"] as! Double) gives you a Double. So you have say (12), then the right side is a Double too (10). So your code ends up looking like (12) += 10 which you can clearly see as problematic, since this is equivalent to 12 = 12 + 10, yikes!
So that being said, you can use the my first solution if you are working with native Swift dictionaries, otherwise your solved solution above works too, just a bit longer.
Lastly, if you are really looking for a one liner that works with your exact situation you should be able to do something like:
dict["number"] = (dict["number"] as! Double) + 10
Another option:
dict["number", default: 0] += 10
The safe way of casting would be:
if let num = dict["number"] as? Double {
dict["number"] = num + 10
}