Swift 2.1 Binary operator * cannot be applied to two String operands - swift

I have a calculator, but I can´t resolve this code:
#IBAction func calcular(sender: AnyObject) {
resultado.text = String(format: "", Sliderdosis)
let peso = pesoLabel.text
let dosis = dosisLabel.text
let total = (peso * dosis) * 5 / 250
/* in this point, the program write:
Binary operator * cannot be applied to two String operands** */
resultado.text = total
}
Some body help me please?
I´m a beginner, sorry!

The infix binary operator * does not exist for type String. You are attempting to multiply String objects (that are, inherently, not numerical) hence the error.
I'd suggest you make use of Leo Dabus excellent UITextField extension, however, in your case, extending UILabel (assuming pesoLabel and dosisLabel are UILabel instances)
extension UILabel {
var stringValue : String { return text ?? "" }
var integerValue: Int { return Int(stringValue) ?? 0 }
var doubleValue : Double { return Double(stringValue) ?? 0 }
var floatValue : Float { return Float(stringValue) ?? 0 }
}
Add this to the header of your .swift file. Thereafter you can update you button action method according to:
#IBAction func calcular(sender: AnyObject) {
resultado.text = String(format: "", Sliderdosis)
let peso = pesoLabel.doubleValue
let dosis = dosisLabel.doubleValue
let total = (peso * dosis) * 5 / 250
resultado.text = String(total)
}
Finally note that this subject is well-covered here on SO, so there exists existing threads that can help you convert string to numerical values. E.g.
Swift - Converting String to Int
Swift - How to convert String to Double
Also have a look at the Asking section here on SO, it contains lots of valuable information of how to ask, when to ask, and so on.

Related

Swift String to Int Always Returns nil

I am trying to convert a String to an Int. Seems simple enough, but for somer reason it is always returning nil.
I'm just writing a simple extension to convert dollars to cents:
func dollarsToCents() -> Int {
var temp = self;
temp = temp.replacingOccurrences(of: "$", with: "")
temp = temp.replacingOccurrences(of: ",", with: "")
if let number = Int(temp) {
return number*100
}
return 0
}
I have temp set to "$250.89". number is always nil. No matter how I approach converting temp to an Int it is always nil. Anyone know what I'm doing wrong?
Problem is, that string "250.89" (after removing currency symbol) can't be converted to Int because 250.89 isn't integer. So fix your code by converting it to Double
func dollarsToCents() -> Int {
var temp = self
temp.removeAll { "$,".contains($0) }
//temp = temp.replacingOccurrences(of: "[$,]", with: "", options: .regularExpression)
return Int(((Double(temp) ?? 0) * 100).rounded())
}
or if your "number" always have two decimal places
func dollarsToCents() -> Int {
var temp = self
temp.removeAll { !("0"..."9" ~= $0) }
return Int(temp) ?? 0
}
But I think solution is much easier. Your goal should be saving price value as number (Double,...). Then you don't have to convert String to Double and you can just multiply your number. Then when you need to add currency symbol, just convert your value to String and add $ or use NumberFormatter
let price = 250.89
let formattedPrice = "$\(price)" // $250.89
let price = 250.89
let formatter = NumberFormatter()
formatter.numberStyle = .currency
formatter.currencyCode = "USD"
let formattedPrice = formatter.string(from: price as NSNumber)! // $250.89
Just adding this for the bizarre edge-case that I just encountered - be sure there aren't any whitespaces either trailing or leading in your string when converting to Int from String.
Eg.
for date in next_thirty_days {
let date_buffer: String = date.description[8...9]
date_list.append(Int(date_buffer)!)
}
This will fail if the value for date_buffer has a leading or trailing white-space.
Another edge-case is that there's a leading 0 in the string variable, eg. 07.
Hope it helps :)

How to get the integer part and fractional part of a number in Swift

This is a super basic question, but, I can't seem to find an answer in Swift.
Question:
How do I get the whole integer part and fractional part (to the left and right of the decimal point respectively) of a number in Swift 2 and Swift 3? For example, for the number 1234.56789 —
How do I get the integer part 1234.56789 ?
How do I get the fractional part 1234.56789 ?
You could do simple floor and truncating:
let value = 1234.56789
let double = floor(value) // 1234.0
let integer = Int(double) // 1234
let decimal = value.truncatingRemainder(dividingBy: 1) // 0.56789
No need for extensions. Swift already has built in function for this.
let aNumber = modf(3.12345)
aNumber.0 // 3.0
aNumber.1 // 0.12345
Swift 4.xm, 5.x complete solution:
I credit #Thomas solution also I'd like to add few things which allow us to use separated parts in 2 string part.
Especially when we want to use 2 different UILabel for main and decimal part of the number.
Extension below is also managing number quantity of decimal part. I thought it might be useful.
UPDATE: Now, it is working perfectly with negative numbers as well!
public extension Double{
func integerPart()->String{
let result = floor(abs(self)).description.dropLast(2).description
let plusMinus = self < 0 ? "-" : ""
return plusMinus + result
}
func fractionalPart(_ withDecimalQty:Int = 2)->String{
let valDecimal = self.truncatingRemainder(dividingBy: 1)
let formatted = String(format: "%.\(withDecimalQty)f", valDecimal)
let dropQuantity = self < 0 ? 3:2
return formatted.dropFirst(dropQuantity).description
}
Convert your number into String later separate string from .
Try this:-
let number:Float = 123.46789
let numberString = String(number)
let numberComponent = numberString.components(separatedBy :".")
let integerNumber = Int(numberComponent [0])
let fractionalNumber = Int(numberComponent [1])
You could do this ->
let x:Double = 1234.5678
let y:Double = Double(Int(x))
let z:Double = x - Double(Int(x))
print("\(x) \(y) \(z)")
Where x is your original value. y is the integer part and z is the fractional part.
Edit
Thomas answer is the one you want ...
This will definitely work for you in swift 5 and 4
let number = 3.145443
let integerValue = String(format: "%.0f", number)
let integerValue1 = String(format: "%.1f", number)
let integerValue2 = String(format: "%.2f", number)
print(integerValue)
print(integerValue1)
print(integerValue2)
//Output
3
3.1
3.14
modf() works bad with numbers > 1 billion
#Trevor behaves like modf()
#Andres Cedronius example behaves like modf() too (i tried modify it)
#Irshad Ahmed solution is nice
there is some convenience convertions
For some reason you need more control, check out https://developer.apple.com/documentation/foundation/numberformatter
extension Double {
/// 1.00234 -> 1.0
var integerPart: Double {
return Double(Int(self))
}
/// 1.0012 --> 0.0012
var fractionPart: Double {
let fractionStr = "0.\(String(self).split(separator: ".")[1])"
return Double(fractionStr)!
}
/// 1.0012 --> "0.0012"
var fractionPartString: String {
return "0.\(String(self).split(separator: ".")[1])"
}
/// 1.0012 --> 12
var fractionPartInteger: Int {
let fractionStr = "\(String(self).split(separator: ".")[1])"
return Int(fractionStr)!
}
}
print(1000.0.integerPart) // 1000.0
print(1000.0.fractionPart) // 0.0
print(1000.1.integerPart) // 1000.0
print(1000.2.fractionPart) // 0.2
print(1_000_000_000.1.integerPart) // 1000000000.0
print(100_000_000.13233.fractionPart) // 0.13233
var specimen0:Double = 1234.56789
var significant0 = Double.IntegerLiteralType(specimen0) // result is an integer
var fractionals0 = specimen0 - Double(significant0)
var specimen1:Float = -1234.56789
var significant1 = Float.IntegerLiteralType(specimen1) // result is an integer
var fractionals1 = specimen1 - Float(significant1)
var specimen2:CGFloat = -1234.56789
var significant2 = CGFloat.IntegerLiteralType(specimen2) // result is an integer
var fractionals2 = specimen2 - CGFloat(significant2)
These are all built in as of Swift 5.3, I am sure even earlier...

Create Simple Class with multiple calculating function( )

Trying to run a simple calculation via a function in my class. I simply want to add bill1 + bill2 and print the total amount spent on bills. So (bill1 + bill2 = total). And then print the total amount.
Current error states - "Code after 'return' will never be executed." Now, is my location for my print in the wrong location or did I declare my variables incorrectly? Should I be using vars instead of lets?
What do you recommend for my function in order to calculate and print the result?
class BillsCalculator
{
let nameOfBill1: String = "Medical"
let nameOfBill1: String = "Hulu"
let monthlyBillAmount1: Double = 34.25
let monthlyBillAmount2: Double = 7.99
let calculateTotalsPerMonth: Double = 0.0
//calculateTotalPerMonth ( = monthlyBillAmount_1 + monthlyBillAmount_2 + 3)
func calculateTotalsPerMonth(monthlyBillAmount: Double, monthlyBillAmount2: Double) -> Double
{
//totalBillsPerMonth = add(monthlyBillAmount1 + monthlyBillAmount2)
return totalBillsPerMonth(monthlyBillAmount1 + monthlyBillAmount2)
*Error println("You spend \(totalBillsPerMonth)")
}
}
First: "Code after 'return' will never be executed."
Yes it will not, after you call return you exit the function and return to the function that call it, you probably have an warning in XCode warning you about telling you that
Second: "Should I be using vars instead of lets"
If the value changes you MUST use var, if it does not you SHOULD use let.
Some problems I can see in your code:
class BillsCalculator
{
//use _ in the beginning of the name for class variables
//eg. _nameOfBill instead nameOfBill1
//It is not wrong use nameOfBill1 is just not recommended
//if nameOfBill1 change use var
let nameOfBill1: String = "Medical"
//Why is this declare twice
let nameOfBill1: String = "Hulu"
//Those values look like change should be var
var monthlyBillAmount1: Double = 34.25
var monthlyBillAmount2: Double = 7.99
var calculateTotalsPerMonth: Double = 0.0
func calculateTotalsPerMonth(monthlyBillAmount: Double, monthlyBillAmount2: Double) -> Double
{
totalBillsPerMonth = add(monthlyBillAmount1 + monthlyBillAmount2)
//print before return
println("You spend \(totalBillsPerMonth)")
return totalBillsPerMonth(monthlyBillAmount1 + monthlyBillAmount2)
}
}
Here you should either print the value of your total bill or return that value. As you just want to print the total bill amount so I would recommend you to just print, not to return anything. You can refer the below code.
class BillsCalculator
{
let nameOfBill1: String = "Medical"
let nameOfBill1: String = "Hulu"
let monthlyBillAmount1: Double = 34.25
let monthlyBillAmount2: Double = 7.99
let calculateTotalsPerMonth: Double = 0.0
//calculateTotalPerMonth ( = monthlyBillAmount_1 + monthlyBillAmount_2 + 3)
func calculateTotalsPerMonth(monthlyBillAmount: Double, monthlyBillAmount2: Double) -> Double
{
calculateTotalsPerMonth= add(monthlyBillAmount1 + monthlyBillAmount2)
println("You spend : "+totalBillsPerMonth);
}
}
One tiny error in your code
let nameOfBill1: String = "Medical"
let nameOfBill1: String = "Hulu"
These two variables have the same name, perhaps one should be:
let nameOfBill2: String = "Hulu"
And yes return is always the last line in the function, so any codes after return will never be executed. If you only want to get the total of two bills, you can simply do this:
func calculateTotalsPerMonth(monthlyBillAmount: Double, monthlyBillAmount2: Double) -> Double {
//println("You spend \(totalBillsPerMonth)")
return monthlyBillAmount1 + monthlyBillAmount2
}
and call this function with your bill variables, like:
let bill1 = 34.25
let bill2 = 7.99
let totalBill = calculateTotalsPerMonth(bill1, bill2)
println("You spent \(totalBill)")
Swift is a very smart language, and it is type safe. You can remove the type if you want, more like a personal programming style thing.
let bill1: Double = 34.25
let bill1 = 34.25
They both will be type "Double"
As others have said, you need to put your println statement before return since returns ends the execution of the method; thus println will never be run.
However, I would suggest a few changes to your current approach:
// A bill is an object - why not encapsulate it in a struct.
struct Bill {
let name: String
let amount: Double
}
// Using structs is generally preferred, unless you need inheritance and/or
// references to your BillsCalculator objects.
struct BillsCalculator {
let bill1: Bill
let bill2: Bill
// Using a read-only computed property means you don't need to set
// the total to have an initial value of zero.
var totalBilled: Double {
return bill1.amount + bill2.amount
}
}
// Since you're probably going to want to reuse BillsCalculator,
// don't have each bill set already. Instead, use BillsCalculator's
// initialiser and pass in bills.
let bill1 = Bill(name: "Medical", amount: 34.25)
let bill2 = Bill(name: "Hulu", amount: 7.99)
let cal = BillsCalculator(bill1: bill1, bill2: bill2)
print("You've spend \(cal.totalBilled) this month")

Trouble using width for String in for-in cycle

I've write a simple code:
extension String {
func trailingSpaces (width: Int) -> String {
var s = "\(self)"
for i in count(s)..<width {
s = s + " "
}
return s
}
func leadingSpaces (width: Int) -> String {
var s = "\(self)"
for i in count(s)..<width {
s = " " + s
}
return s
}
}
class ViewController: UIViewController {
var users = ["Marco", "Gianni", "Antonio", "Giulio", "Franco"]
var ages = [29, 45, 17, 33, 37]
override func viewDidLoad() {
super.viewDidLoad()
var merged = [String: Int] ()
var totalAge = 0.0
for var i = 0; i < ages.count; i++ {
merged[users[i]] = ages[i]
}
for user in sorted(merged.keys) {
let age = merged[user]
totalAge += Double(age!)
let paddedUser = user.trailingSpaces(10)
let paddedAge = "\(age)".leadingSpaces(3)
println("\(paddedUser) \(age!)")
}
println("\n\(merged.count) users")
println("average age: \(totalAge / Double(merged.count))")
}
}
but I can't make it work the leadingSpaces function and I can't understand the reason, it's quite identical to the other extension func that works.
It give the error
fatal error: Can't form Range with end < start
on runtime
in case you run into this kind of problem, always do a println() of the variable you are using
println("\(age)") right before let paddedAge = "\(age!)".leadingSpaces(3)
reveals the problem
age is an optional, meaning that you are trying to do the padding on a String which has this value "Optional(17)"
Thus, your count(s) is higher than 3, and you have an invalid range
Your variable age is not an Int - it's an optional - Int?. You know this already as you are unwrapping it in the lines totalAge += Double(age!) and println("\(paddedUser) \(age!)") - but you are not unwrapping it in the failing line let paddedAge = "\(age)".leadingSpaces(3). The string being passed to leadingSpaces is not "17", it's "Optional(17)", which is why your padding function is failing, as the length is greater than the requested width.
Having said that, as the commentator #milo256 points out, Swift can only iterate upwards, and so unless you put a check on width >= .count in your padding functions they will crash at some point.

Swift double to string

Before I updated xCode 6, I had no problems casting a double to a string but now it gives me an error
var a: Double = 1.5
var b: String = String(a)
It gives me the error message "double is not convertible to string". Is there any other way to do it?
It is not casting, it is creating a string from a value with a format.
let a: Double = 1.5
let b: String = String(format: "%f", a)
print("b: \(b)") // b: 1.500000
With a different format:
let c: String = String(format: "%.1f", a)
print("c: \(c)") // c: 1.5
You can also omit the format property if no formatting is needed.
let double = 1.5
let string = double.description
update Xcode 7.1 • Swift 2.1:
Now Double is also convertible to String so you can simply use it as you wish:
let double = 1.5
let doubleString = String(double) // "1.5"
Swift 3 or later we can extend LosslessStringConvertible and make it generic
Xcode 11.3 • Swift 5.1 or later
extension LosslessStringConvertible {
var string: String { .init(self) }
}
let double = 1.5
let string = double.string // "1.5"
For a fixed number of fraction digits we can extend FloatingPoint protocol:
extension FloatingPoint where Self: CVarArg {
func fixedFraction(digits: Int) -> String {
.init(format: "%.*f", digits, self)
}
}
If you need more control over your number format (minimum and maximum fraction digits and rounding mode) you can use NumberFormatter:
extension Formatter {
static let number = NumberFormatter()
}
extension FloatingPoint {
func fractionDigits(min: Int = 2, max: Int = 2, roundingMode: NumberFormatter.RoundingMode = .halfEven) -> String {
Formatter.number.minimumFractionDigits = min
Formatter.number.maximumFractionDigits = max
Formatter.number.roundingMode = roundingMode
Formatter.number.numberStyle = .decimal
return Formatter.number.string(for: self) ?? ""
}
}
2.12345.fractionDigits() // "2.12"
2.12345.fractionDigits(min: 3, max: 3, roundingMode: .up) // "2.124"
In addition to #Zaph's answer, you can create an extension on Double:
extension Double {
func toString() -> String {
return String(format: "%.1f",self)
}
}
Usage:
var a:Double = 1.5
println("output: \(a.toString())") // output: 1.5
Swift 3+: Try these line of code
let num: Double = 1.5
let str = String(format: "%.2f", num)
to make anything a string in swift except maybe enum values simply do what you do in the println() method
for example:
var stringOfDBL = "\(myDouble)"
There are many answers here that suggest a variety of techniques. But when presenting numbers in the UI, you invariably want to use a NumberFormatter so that the results are properly formatted, rounded, and localized:
let value = 10000.5
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
guard let string = formatter.string(for: value) else { return }
print(string) // 10,000.5
If you want fixed number of decimal places, e.g. for currency values
let value = 10000.5
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
formatter.maximumFractionDigits = 2
formatter.minimumFractionDigits = 2
guard let string = formatter.string(for: value) else { return }
print(string) // 10,000.50
But the beauty of this approach, is that it will be properly localized, resulting in 10,000.50 in the US but 10.000,50 in Germany. Different locales have different preferred formats for numbers, and we should let NumberFormatter use the format preferred by the end user when presenting numeric values within the UI.
Needless to say, while NumberFormatter is essential when preparing string representations within the UI, it should not be used if writing numeric values as strings for persistent storage, interface with web services, etc.
Swift 4:
Use following code
let number = 2.4
let string = String(format: "%.2f", number)
This function will let you specify the number of decimal places to show:
func doubleToString(number:Double, numberOfDecimalPlaces:Int) -> String {
return String(format:"%."+numberOfDecimalPlaces.description+"f", number)
}
Usage:
let numberString = doubleToStringDecimalPlacesWithDouble(number: x, numberOfDecimalPlaces: 2)
In swift 3:
var a: Double = 1.5
var b: String = String(a)
In swift 3 it is simple as given below
let stringDouble = String(describing: double)
I would prefer NSNumber and NumberFormatter approach (where need), also u can use extension to avoid bloating code
extension Double {
var toString: String {
return NSNumber(value: self).stringValue
}
}
U can also need reverse approach
extension String {
var toDouble: Double {
return Double(self) ?? .nan
}
}
var b = String(stringInterpolationSegment: a)
This works for me. You may have a try
In Swift 4 if you like to modify and use a Double in the UI as a textLabel "String" you can add this in the end of your file:
extension Double {
func roundToInt() -> Int{
return Int(Darwin.round(self))
}
}
And use it like this if you like to have it in a textlabel:
currentTemp.text = "\(weatherData.tempCelsius.roundToInt())"
Or print it as an Int:
print(weatherData.tempCelsius.roundToInt())
Swift 5:
Use following code
extension Double {
func getStringValue(withFloatingPoints points: Int = 0) -> String {
let valDouble = modf(self)
let fractionalVal = (valDouble.1)
if fractionalVal > 0 {
return String(format: "%.*f", points, self)
}
return String(format: "%.0f", self)
}
}
You shouldn't really ever cast a double to a string, the most common reason for casting a float to a string is to present it to a user, but floats are not real number and can only approximate lots of values, similar to how ⅓ can not be represented as a decimal number with a finite number of decimal places. Instead keep you values as float for all their use, then when you want to present them to the user, use something like NumberFormater to convert them for your. This stage of converting for user presentation is what something like your viewModel should do.
Use this.
Text(String(format: "%.2f", doubleValue))