Integer literal '4294967295' overflows when stored into 'Int' - swift

I get an error message, when I archive my project. How to fix it? The error is in line number 2.
func random() -> CGFloat{
return CGFloat(CGFloat(arc4random()) / 0xFFFFFFFF)
}
func random(min: CGFloat, max: CGFloat) -> CGFloat{
return random() * (max - min) + min
}

The compiler considers 0xFFFFFFFF as an integer literal, but the
value is too large for a (signed) Int on a 32-bit platform.
Choosing the (unsigned) UInt32 instead solves the problem:
func random() -> CGFloat{
return CGFloat(arc4random()) / CGFloat(UInt32.max)
}

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

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

Rounding INT to make it 0 decimal places

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.

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.

Generating random values in Swift between two integer values

I'm trying to generate random values between two integers. I've tried this, which starts from 0,
let randomNumber = arc4random_uniform(10)
println(randomNumber)
But I need a value between 10 and 50.
try this
let randomNumber = arc4random_uniform(40) + 10
println(randomNumber)
in general form
let lower : UInt32 = 10
let upper : UInt32 = 50
let randomNumber = arc4random_uniform(upper - lower) + lower
println(randomNumber)
This is an option for Swift 4.2 and above using the random() method, which makes it easy!
let randomInt = Int.random(in: 10...50)
The range can be a closed (a...b) or half open (a..<b) range.
If you want a reusable function with simple parameters:
func generateRandomNumber(min: Int, max: Int) -> Int {
let randomNum = Int(arc4random_uniform(UInt32(max) - UInt32(min)) + UInt32(min))
return randomNum
}
more simple way of random number generator
func random(min: Int, max: Int) -> Int {
return Int(arc4random_uniform(UInt32(max - min + 1))) + min
}