Monomeeth
Monomeeth

Reputation: 773

In Swift how do I display a percentage value rounded up or down with no decimal places

I thought this would be fairly straightforward, but I can't seem to work it out or find an existing question that's covers my situation.

Originally I set up a number of variables as follows:

var score :Int! = 0
var totalquestionsasked :Int! = 0
var percentagecorrect :Int! = 0

This got all my values calculating okay, but I ran into problems with the percentage.

My basic formula for the percentage is:

percentagecorrect = score / totalquestionsasked * 100

However, I couldn't get this to display when using the value in a text label.

So after some research, I changed my variables to this instead:

var score :Double = 0.0
var totalquestionsasked :Double = 0.0
var percentagecorrect :Double = 0.0

And still used the same formula for the percentage:

percentagecorrect = score / totalquestionsasked * 100

However, while this displayed okay, I didn't want all the decimal places. So after some more research I came across an extension in another question and adapted it for my application. My extension is:

extension Double {
    var roundTo0f: Double {return Double(round(1*self)/1) }
    var roundTo1f: Double {return Double(round(10*self)/10) }
    var roundTo2f: Double {return Double(round(100*self)/100)  }
    var roundTo3f: Double {return Double(round(1000*self)/1000) }
}

And I've tried using the extension as follows:

percentagecorrect = score / totalquestionsasked * 100
let percentagevalue: Double = percentagecorrect.roundTo0f
labelPercent.text = "\(percentagevalue)"

The end result is that this is pretty close to what I want. However it does still display the percentage to 1 decimal place. (As an aside, it's not accurate - what I mean is that if the score is 1 and the number of questions asked is 3, the above code displays the percentage as 33.0 instead of 33.3, but I digress)

What I'm actually wanting is the value to round up or down to the nearest whole number before displaying the value. In other words, what I want is

That is I want no decimal places at all in the displayed result. At present, it rounds up/down correctly but sill displays ".0" at the end. If this isn't possible, then I want it to display to one decimal place correctly.

I am new to programming and Swift is the first language I'm trying to learn, so maybe this is just a newbie mistake, but I really can't find what I'm doing wrong.

How do I get this to work?

Upvotes: 17

Views: 26769

Answers (5)

user5735326
user5735326

Reputation:

You can use this extension:

extension Double {
/// Rounds the double to decimal places value
func roundToPlaces(places:Int) -> Double {
    let divisor = pow(10.0, Double(places))
    return round(self * divisor) / divisor
}
}

Upvotes: 0

Mountain Man
Mountain Man

Reputation: 242

You can do the round off yourself. I am assuming a one for one answer score valuation. I've plugged in some numbers so you can paste this into a playground. You can change to value in "if left" to anything you want. .51 etc. Just because the IRS has you round off at 50 cents that doesn't mean you have to.

var score :Double! = 359
var totalquestionsasked :Double! = 400
var percentagecorrect :Double! = (score / totalquestionsasked) * 100
var left = percentagecorrect - Double(Int(percentagecorrect))
if left >=  0.50 {

    percentagecorrect = percentagecorrect + 1.0

}
 var answer = Int(percentagecorrect)

Upvotes: 1

totiDev
totiDev

Reputation: 5275

You can use the built in round function and cast to an Int.

print(Int(round(33.3)))
print(Int(round(66.6)))

If you want an extension method to return a string, you can use this:

extension Double {
    func roundTo(decimalPlaces: Int) -> String {
        return NSString(format: "%.\(decimalPlaces)f", self) as String
    }
}

Upvotes: 21

Martin R
Martin R

Reputation: 539965

In pure integer arithmetic,

var score : Int = ...
var totalquestionsasked : Int = ...
let percentagecorrect = (score * 200 + totalquestionsasked)/(2 * totalquestionsasked)

would do the trick.


How does this work? Computing the percentage as

(score * 100)/totalquestionsasked

truncates the result of the division towards zero. For the desired rounding behavior, we would have to compute

(score * 100)/totalquestionsasked + 1/2

in floating point arithmetic and then truncate the result to an integer. Combining terms give the expression

(score * 200 + totalquestionsasked)/(2 * totalquestionsasked)

which, when computed in integer arithmetic, gives the correct result.

Upvotes: 4

Christian Abella
Christian Abella

Reputation: 5797

You can use the format specifier of NSString and add it to your Double extension as functions.

extension Double
{
  func roundTo0f() -> NSString
  {
    return NSString(format: "%.0f", self)
  }

  func roundTo1f() -> NSString
  {
    return NSString(format: "%.1f", self)
  }

  func roundTo2f() -> NSString
  {
    return NSString(format: "%.2f", self)
  }

  func roundToNf(n : Int) -> NSString
  {
    return NSString(format: "%.\(n)f", self)
  }
} 

let d : Double = 9.12
print(d.roundTo0f())
print(d.roundTo1f())
print(d.roundTo2f())

Upvotes: 3

Related Questions