Need explanation about random function swift - 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)
}

Related

Round Half Down in Swift

Is there a rounding mode in Swift that behaves same as ROUND_HALF_DOWN in Java?
Rounding mode to round towards "nearest neighbor" unless both neighbors are equidistant, in which case round down. Behaves as for RoundingMode.UP if the discarded fraction is > 0.5; otherwise, behaves as for RoundingMode.DOWN.
Example:
2.5 rounds down to 2.0
2.6 rounds up to 3.0
2.4 rounds down to 2.0
For a negative number:
-2.5 rounds up to -2.0
-2.6 rounds down to -3.0
-2.4 rounds up to -2.0
There is – as far as I can tell – no FloatingPointRoundingRule with the same behavior as Java's ROUND_HALF_DOWN, but you can get the result with a combination of rounded() and nextDown or nextUp:
func roundHalfDown(_ x: Double) -> Double {
if x >= 0 {
return x.nextDown.rounded()
} else {
return x.nextUp.rounded()
}
}
Examples:
print(roundHalfDown(2.4)) // 2.0
print(roundHalfDown(2.5)) // 2.0
print(roundHalfDown(2.6)) // 3.0
print(roundHalfDown(-2.4)) // -2.0
print(roundHalfDown(-2.5)) // -2.0
print(roundHalfDown(-2.6)) // -3.0
Or as a generic extension method, so that it can be used with all floating point types (Float, Double, CGFloat):
extension FloatingPoint {
func roundedHalfDown() -> Self {
return self >= 0 ? nextDown.rounded() : nextUp.rounded()
}
}
Examples:
print((2.4).roundedHalfDown()) // 2.0
print((2.5).roundedHalfDown()) // 2.0
print((2.6).roundedHalfDown()) // 3.0
print((-2.4).roundedHalfDown()) // -2.0
print((-2.5).roundedHalfDown()) // -2.0
print((-2.6).roundedHalfDown()) // -3.0
Swift implements .round() function with rules, According to Apple
FloatingPointRoundingRule
case awayFromZero
Round to the closest allowed value whose magnitude is greater than or equal to that of the source.
case down
Round to the closest allowed value that is less than or equal to the source.
case toNearestOrAwayFromZero
Round to the closest allowed value; if two values are equally close, the one with greater magnitude is chosen.
case toNearestOrEven
Round to the closest allowed value; if two values are equally close, the even one is chosen.
case towardZero
Round to the closest allowed value whose magnitude is less than or equal to that of the source.
case up
Round to the closest allowed value that is greater than or equal to the source.
Yes, You can do the similar things using NSNumberFormatter and RoundingMode
Read them here
NSNumberFormatter
RoundingMode
var a = 6.54
a.round(.toNearestOrAwayFromZero)
// a == 7.0
var b = 6.54
b.round(.towardZero)
// b == 6.0
var c = 6.54
c.round(.up)
// c == 7.0
var d = 6.54
d.round(.down)
// d == 6.0
You can do like this as well but need to take values after decimal as well.
As #MohmmadS said those are built in methods for rounding.
You can implement custom rounding like this:
func round(_ value: Double, toNearest: Double) -> Double {
return round(value / toNearest) * toNearest
}
func roundDown(_ value: Double, toNearest: Double) -> Double {
return floor(value / toNearest) * toNearest
}
func roundUp(_ value: Double, toNearest: Double) -> Double {
return ceil(value / toNearest) * toNearest
}
Example:
round(52.376, toNearest: 0.01) // 52.38
round(52.376, toNearest: 0.1) // 52.4
round(52.376, toNearest: 0.25) // 52.5
round(52.376, toNearest: 0.5) // 52.5
round(52.376, toNearest: 1) // 52

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

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

Receiving NaN as an output when using the pow() function to generate a Decimal

I've been at this for hours so forgive me if I'm missing something obvious.
I'm using the pow(_ x: Decimal, _ y: Int) -> Decimal function to help generate a monthly payment amount using a basic formula. I have this function linked to the infix operator *** but I've tried using it just by typing out the function and have the same problem.
Xcode was yelling at me yesterday for having too long of a formula, so I broke it up into a couple constants and incorporated that into the overall formula I need.
Code:
precedencegroup PowerPrecedence { higherThan: MultiplicationPrecedence }
infix operator *** : PowerPrecedence
func *** (radix: Decimal, power: Int) -> Decimal {
return (pow((radix), (power)))
}
func calculateMonthlyPayment() {
let rateAndMonths: Decimal = ((0.0199 / 12.0) + (0.0199 / 12.0))
let rateTwo: Decimal = ((1.0+(0.0199 / 12.0)))
loan12YearsPayment[0] = ((rateAndMonths / rateTwo) *** 144 - 1.0) * ((values.installedSystemCost + loanFees12YearsCombined[0]) * 0.7)
When I print to console or run this in the simulator, the output is NaN. I know the pow function itself is working properly because I've tried it with random integers.
Kindly find my point of view for this Apple function implementation, Note the following examples:
pow(1 as Decimal, -2) // 1; (1 ^ Any number) = 1
pow(10 as Decimal, -2) // NAN
pow(0.1 as Decimal, -2) // 100
pow(0.01 as Decimal, -2) // 10000
pow(1.5 as Decimal, -2) // NAN
pow(0.5 as Decimal, -2) // NAN
It seems like, pow with decimal don't consider any floating numbers except for 10 basis. So It deals with:
0.1 ^ -2 == (1/10) ^ -2 == 10 ^ 2 // It calculates it appropriately, It's 10 basis 10, 100, 1000, ...
1.5 ^ -2 == (3/2) ^ -2 // (3/2) is a floating number ,so deal with it as Double not decimal, It returns NAN.
0.5 ^ -2 == (1/2) ^ -2 // (2) isn't 10 basis, So It will be dealt as (1/2) as It is, It's a floating number also. It returns NAN.

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.