Reputation: 773
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
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
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
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
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
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