Rounding INT to make it 0 decimal places - swift

I am running the following code with a round function.
let percentage = round((progress / maxValue) * 100)
However it keeps returning numbers like: 15.0, 25.0, 35.0 etc.
I want it to return: 15, 25, 35, basically 0 decimal places.
How can I do this?
Cheers! :D

That's because round() returns a floating point number, not an integer:
If you want an integer, you have to convert it:
let percentage = Int(round((progress / maxValue) * 100))

Cast it to an Int:
let percentage = round((progress / maxValue) * 100)
let percentageInt = Int(percentage)

round() returns a floating point number. You can convert the result
to an Int, or call lrint instead:
let percentage = lrint((progress / maxValue) * 100)
The functions
public func lrintf(_: Float) -> Int
public func lrint(_: Double) -> Int
return the integral value nearest to their argument as an integer.

Related

Need explanation about random function swift

Got a question about my random function: why is it giving this error?
'4294967295' is not exactly representable as 'Float'; it becomes '4294967296'
-
my code is
func random() ->CGFloat {
return CGFloat(Float(arc4random()) / 0xFFFFFFFF)
}
func random(min: CGFloat, max: CGFloat) -> CGFloat {
return random() * (max - min) + min
}
it doesn't change the functionality of the application but it just appeared out of nowhere.
thanks in advance!
A IEEE 754 32-bit floating point number has 24 significant bits for the mantissa, that is not enough to store a 10-digit integer exactly:
print(0xFFFFFFFF) // 4294967295
print(Float(0xFFFFFFFF)) // 4.2949673e+09
print(Int(Float(0xFFFFFFFF))) // 4294967296
That won't affect your code because
Float(arc4random()) / Float(0xFFFFFFFF)
is still a floating point number between 0.0 and 1.0. Changing the calculation to
return CGFloat(arc4random()) / 0xFFFFFFFF
will fix the warning on 64-bit platforms: The integer constant is now converted to a (64-bit) Double.
But as of Swift 4.2 you can avoid the problem completely by using the new Random API:
func random(min: CGFloat, max: CGFloat) -> CGFloat {
return CGFloat.random(in: min...max)
}

Get double hours from double minute in Swift 2

I'm using Swift 2. I have double myMinute and I want to convert it to double hours(myHours). How can I do it? My codes under below
let myMinute : Double = 62.0
let myHours : Double = ?
I want to show with math example: myhours = 1.0
Found this here!
func minutesToHoursMinutes (minutes : Int) -> (hours : Int , leftMinutes : Int {
return (minutes / 60, (minutes % 60))
}
let timeTuple = minutesToHoursMinutes(minutes: 100)
timeTuple.hours /// 1
timeTuple.leftMinutes /// 40
The value should be 1.03 not 1.02 if you use the current value of minute (you can check with calculator) and it is a simple math, i think what you want beside the calculation is how to round the value to 2 decimal point. You should've made it clearer. This will do the work.
myHours = Double(round(myMinute / 60 * 100) / 100)
print(myHours)

Rounding Numbers to Two Significant Figures

I am sure this is an easy question to any of you are experienced in Swift, however, I just started learning how to program and have no idea where to start. What I am trying to do is a round a number to the nearest whole value, or to the third number. This is what I mean:
12.6 //Want rounded to 13
126 //Want rounded to 130
1264 //Want rounded to 1300
I know swift has a .rounded() function, and I have managed to use it to round the nearest 10th, 100th, etc., however, I cannot round the way I would like to. Any advice would be much appreciated.
Here's one way to round any Double or Int (including negative numbers) to a given number of significant figures:
func round(_ num: Double, to places: Int) -> Double {
let p = log10(abs(num))
let f = pow(10, p.rounded() - Double(places) + 1)
let rnum = (num / f).rounded() * f
return rnum
}
func round(_ num: Int, to places: Int) -> Int {
let p = log10(abs(Double(num)))
let f = pow(10, p.rounded() - Double(places) + 1)
let rnum = (Double(num) / f).rounded() * f
return Int(rnum)
}
print(round(0.265, to: 2))
print(round(1.26, to: 2))
print(round(12.6, to: 2))
print(round(126, to: 2))
print(round(1264, to: 2))
Output:
0.27
1.3
13.0
130
1300
As stated by Sulthan you can use NumberFormatter:
let formatter = NumberFormatter()
formatter.usesSignificantDigits = true
formatter.maximumSignificantDigits = 2
formatter.minimumSignificantDigits = 2
if let result = formatter.string(from: 12.6) {
print(result) // prints 13
}
One possibility to implement a rounding algorithm. I suppose you always want the result to be integer.
func round(_ number: Float, to digits: Int) -> Float {
guard number >= 0 else {
return -round(-number, to: digits)
}
let max = pow(10, Float(digits))
var numZeros = 0
var value = number
while (value >= max) {
value /= 10
numZeros += 1
}
return round(value) * pow(10, Float(numZeros))
}
print(round(12.6, to: 2)) // 13
print(round(126, to: 2)) // 130
print(round(1264, to: 2)) // 1300

Increase random number probability swift

I'm trying to make a game where the hero damage is generated randomly within a range but the more luck the hero has, the higher probability the hero will have to hit with the max damage number within that range.
I'm using a Double extension to make it easier on myself.
public extension Double {
public static func random(lower: Double = 0, _ upper: Double = 100) -> Double {
return (Double(arc4random()) / 0xFFFFFFFF) * (upper - lower) + lower
}
//Assigning the random number to a constant
let heroDamage = Double.random(5, 15)
Let's say the hero has now an 80% of probability on getting the max damage(in this case 15), how would I approach this?, Thanks in advance.
For a given max damage probability of pMaxDamage (say, pMaxDamage = 0.80), one simple solution is to generate a random number, say r, in [0,1] and output:
maxDamage if r <= pMaxDamage,
a random damage in range [minDamage, maxDamage], otherwise.
E.g.:
class Hero {
let heroName: String
let pMaxDamage: Double // probability to generate max damage
init(heroName: String, pMaxDamage: Double) {
self.heroName = heroName
self.pMaxDamage = pMaxDamage
}
func generateDamage(minDamage minDamage: Double, maxDamage: Double) -> Double {
let r = (Double(arc4random()) / 0xFFFFFFFF)
return r <= pMaxDamage ? maxDamage
: round(100*((r-pMaxDamage)/(1-pMaxDamage)*(minDamage-maxDamage)+maxDamage))/100
}
}
For the above implementation the r-damage (r uniform random number in [0, 1]) response curve looks as follows:
Example usage:
let myHero = Hero(heroName: "Foo", pMaxDamage: 0.80)
for _ in (1...10) {
print("Slash! <\(myHero.generateDamage(minDamage: 5, maxDamage: 15)) damage>")
}
Example output:
Slash! <15.0 damage>
Slash! <12.68 damage>
Slash! <15.0 damage>
Slash! <15.0 damage>
Slash! <5.72 damage>
Slash! <15.0 damage>
Slash! <15.0 damage>
Slash! <15.0 damage>
Slash! <15.0 damage>
Slash! <15.0 damage>
If you want your damage values to only take integer values, an alternative solution would be roulette wheel selection with
pMaxDamage probability of picking maxDamage,
uniform (1-pMaxDamage)/(numDamagePoints-1) probability of picking any of the remaining {minDamage, minDamage+1, ..., maxDamage-1} damage values.
Maybe add a luck to the random function? Pure linear implementation here. You could use some advanced curves though.
private let MaxLuck = 1000.0
public extension Double {
public static func random(lower: Double = 0, _ upper: Double = 100, luck: Double) -> Double {
let weight = min(luck / MaxLuck, 1)
return (Double(arc4random()) / 0xFFFFFFFF) * weight * (upper - lower) + lower
}
}

How to generate a float between 1 and 100

I am trying to generate random floats between 1 and 100, but I keep getting errors everytime. Currently I am trying:
func returnDbl ()-> Double {
var randNum = Double(Float(arc4random(101) % 5))
return randNum
}
print(returnDbl())
but to no avail, would someone point me in the right direction?
arc4random is zero-based and returns values between 0 and n-1, pass 100 as the upper bounds and add 1
arc4random_uniform is easier to use, it returns an Int32 type which has to be converted to Float.
func randomFloat() -> Float {
return Float(arc4random_uniform(100) + 1)
}
or Double
func randomDouble() -> Double {
return Double(arc4random_uniform(100) + 1)
}
or generic
func returnFloatingPoint<T : FloatingPointType>()-> T {
return T(arc4random_uniform(100) + 1)
}
let float : Float = returnFloatingPoint()
let double : Double = returnFloatingPoint()
Edit
To return a non-integral Double between 1.000000 and 99.99999 with arc4random_uniform() use
func returnDouble()-> Double {
return Double(arc4random_uniform(UInt32.max)) / 0x100000000 * 99.0 + 1.0
}
0x100000000 is UInt32.max + 1
let a = 1 + drand48() * 99
drand48 is a C function that returns a double in the range [0, 1). You can call it directly from Swift. Multiplying by 99 gives you a double in the range [0, 99). Add one to get into the range [1, 100).
As drand48 returns a double, the Swift type will be Double.
As per the comment, drand48 will by default return the same sequence of numbers upon every launch. You can avoid that by seeding it. E.g.
seed48(UnsafeMutablePointer<UInt16>([arc4random(), arc4random()]))
func returnDbl ()-> Double {
var randNum = Double(Float(arc4random() % 101))
return randNum
}
Ok thank you everybody for all of your help, the setups you showed me helped me figure out how the setup should at least look, my end result is
func returnDbl ()-> Double{
var randNum = Double(Float(arc4random_uniform(99)+1)) / Double(UINT32_MAX)
return randNum
}
print(returnDbl())
it returns floats between 1 and 100.