How to check in Swift an integer is in range of thousands? - swift

In a loop I need to check if n index is a number in a range of thousands:
0...1000
1001...2000
2001...3000
and so on
How can I do that instead to define manually a range?

To get the range of numbers, I divided the number by 1000 and find the range according to the result.
let inputNumber = 6598
let dividedNumber: Float = Float(inputNumber) / 1000.0
if dividedNumber.rounded(.up) == dividedNumber.rounded(.down){
//number is integer
let end: Int = Int(dividedNumber.rounded(.down) * 1000)
let start: Int = end - 1000
print("Range is integer : ", (start + 1)...end)
} else {
//number is not integer
let start: Int = Int(dividedNumber.rounded(.down) * 1000)
let end: Int = Int(start + 1000)
print("Range is not integer : ", (start + 1)...end )
}

This function will help you to check if your number is in Thousands range or not
func checkNumberRange(withNumber myNumber: Double) {
// let reminder = myNumber.truncatingRemainder(dividingBy: 1) // if you wanna get reminder "Floating point"
let start = floor(myNumber)
let end = round(myNumber) + 1000
if ((myNumber / 1000 >= 1) && (myNumber / 1000 <= 1000)) {
print("range from \(start)...\(end)")
}
else {
print("your number isn't in thousands range")
}
}
checkNumberRange(withNumber: 10000067) //your number isn't in thousands range
checkNumberRange(withNumber: 12458.8) //range from 12458.0...13459.0
checkNumberRange(withNumber: 999) //your number isn't in thousands range
checkNumberRange(withNumber: 1000) //range from 1000.0...2000.0
I hope it will help you

Related

How can I write the code of Bessel function with 10 term in swift?

I hope you guys can check. when I use 5 as x it should be showing me -0.17749282815107623 but it returns -0.2792375. I couldn't where I have been doing the mistake.
var evenNumbers = [Int]()
for i in 2...10 {
if i % 2 == 0 {
evenNumbers.append(i)
}
}
func power(val: Float, power: Int)->Float{
var c:Float = 1
for i in 1...power {
c *= val
}
return c
}
func bessel(x: Float)->Float{
var j0:Float = 0
var counter = 1
var lastDetermVal:Float = 1
for eNumber in evenNumbers {
print(lastDetermVal)
if counter == 1 {
lastDetermVal *= power(val: Float(eNumber), power: 2)
j0 += (power(val: x, power: eNumber))/lastDetermVal
counter = -1
}else if counter == -1{
lastDetermVal *= power(val: Float(eNumber), power: 2)
j0 -= (power(val: x, power: eNumber))/lastDetermVal
counter = 1
}
}
return 1-j0
}
bessel(x: 5)
Function 1:
Your mistake seems to be that you didn't have enough even numbers.
var evenNumbers = [Int]()
for i in 2...10 {
if i % 2 == 0 {
evenNumbers.append(i)
}
}
After the above is run, evenNumbers will be populated with [2,4,6,8,10]. But to evaluate 10 terms, you need even numbers up to 18 or 20, depending on whether you count 1 as a "term". Therefore, you should loop up to 18 or 20:
var evenNumbers = [Int]()
for i in 2...18 { // I think the 1 at the beginning should count as a "term"
if i % 2 == 0 {
evenNumbers.append(i)
}
}
Alternatively, you can create this array like this:
let evenNumbers = (1..<10).map { $0 * 2 }
This means "for each number between 1 (inclusive) and 10 (exclusive), multiply each by 2".
Now your solution will give you an answer of -0.1776034.
Here's my (rather slow) solution:
func productOfFirstNEvenNumbers(_ n: Int) -> Float {
if n == 0 {
return 1
}
let firstNEvenNumbers = (1...n).map { Float($0) * 2.0 }
// ".reduce(1.0, *)" means "multiply everything"
return firstNEvenNumbers.reduce(1.0, *)
}
func nthTerm(_ n: Int, x: Float) -> Float {
let numerator = pow(x, Float(n) * 2)
// yes, this does recalculate the product of even numbers every time...
let product = productOfFirstNEvenNumbers(n)
let denominator = product * product
return numerator / (denominator) * pow(-1, Float(n))
}
func bessel10Terms(x: Float) -> Float {
// for each number n in the range 0..<10, get the nth term, add them together
(0..<10).map { nthTerm($0, x: x) }.reduce(0, +)
}
print(bessel10Terms(x: 5))
You code is a bit unreadable, however, I have written a simple solution so try to compare your intermediate results:
var terms: [Float] = []
let x: Float = 5
for index in 0 ..< 10 {
guard index > 0 else {
terms.append(1)
continue
}
// calculate only the multiplier for the previous term
// - (minus) to change the sign
// x * x to multiply nominator
// (Float(index * 2) * Float(index * 2) to multiply denominator
let termFactor = -(x * x) / (Float(index * 2) * Float(index * 2))
terms.append(terms[index - 1] * termFactor)
}
print(terms)
// sum the terms
let result = terms.reduce(0, +)
print(result)
One of the errors I see is the fact that you are actually calculating only 5 terms, not 10 (you iterate 1 to 10, but only even numbers).

Convert decimal to hours:minutes:seconds

I am storing numbers in a MySQL DB as doubles so I can get min, max and sums.
I have a decimal number 1.66777777778 which equals 01:40:04 however I am wanting to be able to convert this decimal in to hour:minutes:seconds in Swift so I can display the value as 01:40:04 however I don't know how.
I have done some searching but most results are calculators without explanation.
I have this function to convert to decimal:
func timeToHour(hour: String, minute:String, second:String) -> Double
{
var hourSource = 0.00
if hour == ""
{
hourSource = 0.00
}
else
{
hourSource = Double(hour)!
}
let minuteSource = Double(minute)!
let secondSource = Double(second)!
let timeDecimal: Double = hourSource + (minuteSource / 60) + (secondSource / 3600)
return timeDecimal
}
but need one to go back the other way.
Thanks
Try:
func hourToString(hour:Double) -> String {
let hours = Int(floor(hour))
let mins = Int(floor(hour * 60) % 60)
let secs = Int(floor(hour * 3600) % 60)
return String(format:"%d:%02d:%02d", hours, mins, secs)
}
Basically break each component out and concatenate them all together.

Generate random number of certain amount of digits

Hy,
I have a very Basic Question which is :
How can i create a random number with 20 digits no floats no negatives (basically an Int) in Swift ?
Thanks for all answers XD
Step 1
First of all we need an extension of Int to generate a random number in a range.
extension Int {
init(_ range: Range<Int> ) {
let delta = range.startIndex < 0 ? abs(range.startIndex) : 0
let min = UInt32(range.startIndex + delta)
let max = UInt32(range.endIndex + delta)
self.init(Int(min + arc4random_uniform(max - min)) - delta)
}
}
This can be used this way:
Int(0...9) // 4 or 1 or 1...
Int(10...99) // 90 or 33 or 11
Int(100...999) // 200 or 333 or 893
Step 2
Now we need a function that receive the number of digits requested, calculates the range of the random number and finally does invoke the new initializer of Int.
func random(digits:Int) -> Int {
let min = Int(pow(Double(10), Double(digits-1))) - 1
let max = Int(pow(Double(10), Double(digits))) - 1
return Int(min...max)
}
Test
random(1) // 8
random(2) // 12
random(3) // 829
random(4) // 2374
Swift 5: Simple Solution
func random(digits:Int) -> String {
var number = String()
for _ in 1...digits {
number += "\(Int.random(in: 1...9))"
}
return number
}
print(random(digits: 1)) //3
print(random(digits: 2)) //59
print(random(digits: 3)) //926
Note It will return value in String, if you need Int value then you can do like this
let number = Int(random(digits: 1)) ?? 0
Here is some pseudocode that should do what you want.
generateRandomNumber(20)
func generateRandomNumber(int numDigits){
var place = 1
var finalNumber = 0;
for(int i = 0; i < numDigits; i++){
place *= 10
var randomNumber = arc4random_uniform(10)
finalNumber += randomNumber * place
}
return finalNumber
}
Its pretty simple. You generate 20 random numbers, and multiply them by the respective tens, hundredths, thousands... place that they should be on. This way you will guarantee a number of the correct size, but will randomly generate the number that will be used in each place.
Update
As said in the comments you will most likely get an overflow exception with a number this long, so you'll have to be creative in how you'd like to store the number (String, ect...) but I merely wanted to show you a simple way to generate a number with a guaranteed digit length. Also, given the current code there is a small chance your leading number could be 0 so you should protect against that as well.
you can create a string number then convert the number to your required number.
func generateRandomDigits(_ digitNumber: Int) -> String {
var number = ""
for i in 0..<digitNumber {
var randomNumber = arc4random_uniform(10)
while randomNumber == 0 && i == 0 {
randomNumber = arc4random_uniform(10)
}
number += "\(randomNumber)"
}
return number
}
print(Int(generateRandomDigits(3)))
for 20 digit you can use Double instead of Int
Here is 18 decimal digits in a UInt64:
(Swift 3)
let sz: UInt32 = 1000000000
let ms: UInt64 = UInt64(arc4random_uniform(sz))
let ls: UInt64 = UInt64(arc4random_uniform(sz))
let digits: UInt64 = ms * UInt64(sz) + ls
print(String(format:"18 digits: %018llu", digits)) // Print with leading 0s.
16 decimal digits with leading digit 1..9 in a UInt64:
let sz: UInt64 = 100000000
let ld: UInt64 = UInt64(arc4random_uniform(9)+1)
let ms: UInt64 = UInt64(arc4random_uniform(UInt32(sz/10)))
let ls: UInt64 = UInt64(arc4random_uniform(UInt32(sz)))
let digits: UInt64 = ld * (sz*sz/10) + (ms * sz) + ls
print(String(format:"16 digits: %llu", digits))
Swift 3
appzyourlifz's answer updated to Swift 3
Step 1:
extension Int {
init(_ range: Range<Int> ) {
let delta = range.lowerBound < 0 ? abs(range.lowerBound) : 0
let min = UInt32(range.lowerBound + delta)
let max = UInt32(range.upperBound + delta)
self.init(Int(min + arc4random_uniform(max - min)) - delta)
}
}
Step 2:
func randomNumberWith(digits:Int) -> Int {
let min = Int(pow(Double(10), Double(digits-1))) - 1
let max = Int(pow(Double(10), Double(digits))) - 1
return Int(Range(uncheckedBounds: (min, max)))
}
Usage:
randomNumberWith(digits:4) // 2271
randomNumberWith(digits:8) // 65273410
Swift 4 version of Unome's validate response plus :
Guard it against overflow and 0 digit number
Adding support for Linux's device because "arc4random*" functions don't exit
With linux device don't forgot to do
#if os(Linux)
srandom(UInt32(time(nil)))
#endif
only once before calling random.
/// This function generate a random number of type Int with the given digits number
///
/// - Parameter digit: the number of digit
/// - Returns: the ramdom generate number or nil if wrong parameter
func randomNumber(with digit: Int) -> Int? {
guard 0 < digit, digit < 20 else { // 0 digit number don't exist and 20 digit Int are to big
return nil
}
/// The final ramdom generate Int
var finalNumber : Int = 0;
for i in 1...digit {
/// The new generated number which will be add to the final number
var randomOperator : Int = 0
repeat {
#if os(Linux)
randomOperator = Int(random() % 9) * Int(powf(10, Float(i - 1)))
#else
randomOperator = Int(arc4random_uniform(9)) * Int(powf(10, Float(i - 1)))
#endif
} while Double(randomOperator + finalNumber) > Double(Int.max) // Verification to be sure to don't overflow Int max size
finalNumber += randomOperator
}
return finalNumber
}

Swift Random Number Generator in increments of 25

extension Int
{
static func random(range: Range<Int> ) -> Int
{
var offset = 0
if range.startIndex < 0 // allow negative ranges
{
offset = abs(range.startIndex)
}
let mini = UInt32(range.startIndex + offset)
let maxi = UInt32(range.endIndex + offset)
return Int(mini + arc4random_uniform(maxi - mini)) - offset
}
}
How can I modify this to only spit out increments of 25? For example:
random(150...250)
would possibly give me 150, 175, 200, 225, and 250 and nothing between those.
I know I could just check if it is divisble by 25 but then who knows how many times it has to 'roll again' to find a number that is accepted. I am looking for something a little more optimized and/or cleaner in code. To be fair, I have no idea how fast the arc4random_uniform function is.
var num = 150 + ( random(0...4) * 25)
func random25(min: Int, max: Int) -> Int {
assert(max > min)
let minIndex = min / 25
let r = arc4random_uniform(UInt32(max / 25 - minIndex))
return (Int(r) + minIndex) * 25
}
func randomRange(range: Range<Int>, increment:Int ) -> Int {
if Int(range.endIndex-1) % increment != 0 { return 0 }
if increment > (Int(range.endIndex-1 ) - Int(range.startIndex )) { return 0 }
if increment == 1 { return Int( arc4random_uniform( UInt32( Int(range.endIndex) - Int(range.startIndex) ) ) ) + Int(range.startIndex) }
let numberOfRandomElements = ( ( Int(range.endIndex ) - Int(range.startIndex )) / increment ) + 1
let randomAux = Int(arc4random_uniform(UInt32(numberOfRandomElements)))
return randomAux * increment + Int(range.startIndex)
}
randomRange(100...250, 25)
randomRange(100...250, 25)
randomRange(100...250, 25)
randomRange(100...250, 25)
randomRange(100...250, 25)
randomRange(100...250, 25)
randomRange(100...250, 5)
randomRange(100...250, 5)
randomRange(100...250, 5)
randomRange(100...250, 5)
randomRange(100...250, 5)
randomRange(100...250, 5)
randomRange(100...250, 5)
Here's a flexible implementation for producing random integers within ranges and with constant intervals. Run it in a playground and use menu command Editor > Execute Playground to test through the multiple random results.
import Foundation
/// Returns an integer within the specified range,
/// skipping values between intervals. Interval values are calculated
/// starting from the range's startIndex for positive intervals
/// and from the endIndex for negative intervals.
func randomInRange(range: Range<Int>, withInterval interval: Int = 1) -> Int {
assert(interval != 0, "Function failed because increment argument is zero")
let startIndex = range.startIndex
let endIndex = range.endIndex
assert(endIndex > startIndex, "Function failed because range's endIndex is not greater than startIndex")
let penultimateIndex = endIndex - 1
let possibilityCount = abs((penultimateIndex - startIndex) / interval) + 1
let randomOffset = Int(arc4random_uniform(UInt32(possibilityCount))) * interval
if interval > 0 {
return startIndex + randomOffset
} else {
return penultimateIndex + randomOffset
}
}
randomInRange(150...250, withInterval: 25) // As per OP's request
randomInRange(0..<2, withInterval: 1) // Only produces 0 or 1
randomInRange(0...2, withInterval: 1)
randomInRange(0...2) // Interval of 1 assumed
randomInRange(0...2, withInterval: 2)
randomInRange(0...2, withInterval: 3) // Only produces 0
randomInRange(0...2, withInterval: -3) // Only produces 2
randomInRange(0...4, withInterval: 2)
randomInRange(0...6, withInterval: 3)
randomInRange(0...6, withInterval: 4) // Only produces 0 or 4
randomInRange(0...6, withInterval: -4) // Only produces 6 or 2
randomInRange(1...10, withInterval: 3) // Produces 1, 4, 7, or 10
randomInRange(-3...3, withInterval: 3)
randomInRange(-7...5, withInterval: 3) // Produces values that are not multiples of the interval
randomInRange(0...100, withInterval: 25)
randomInRange(0...100, withInterval: -33) // Produces 100, 67, 34, or 1
randomInRange(0...0, withInterval: 1) // Only produces 0
// randomInRange(Range(start: 0, end: 0), withInterval: 1) // Assertion error for empty range
// randomInRange(0...100, withInterval: 0) // Assertion error for interval of 0
/// Returns an optional integer within the specified range,
/// skipping values between intervals.
/// If the range's startIndex and endIndex-1 are not multiples of the interval,
/// the function adjusts these values in a narrower range with start and end indices at interval multiples.
/// If no multiple of the interval exists in the given range, returns nil.
func randomInRange(range: Range<Int>, atMultipleOfInterval interval: Int) -> Int? {
assert(interval != 0, "Function failed because increment argument is zero")
let startIndex = range.startIndex
let endIndex = range.endIndex
assert(endIndex > startIndex, "Function failed because range's endIndex is not greater than startIndex")
let penultimateIndex = endIndex - 1
if (startIndex % interval != 0) || (penultimateIndex % interval != 0) {
let adjustedStart = startIndex - startIndex % interval + interval
let adjustedPenultimate: Int = penultimateIndex - penultimateIndex % interval
if adjustedPenultimate >= adjustedStart {
return randomInRange(adjustedStart...adjustedPenultimate, withInterval: interval)
} else {
return nil
}
} else {
return randomInRange(startIndex...penultimateIndex, withInterval: interval)
}
}
randomInRange(0...10, atMultipleOfInterval: 5)
randomInRange(2...4, atMultipleOfInterval: 5) // Produces nil
randomInRange(7...13, atMultipleOfInterval: 10)
randomInRange(1...500, atMultipleOfInterval: 7)
randomInRange(300...300, atMultipleOfInterval: 25)
// With random range, return only random values that are multiples of the random interval
let interval = Int(arc4random_uniform(25)) + 1
var startIndex = Int(arc4random_uniform(500)) - 250
var penultimateIndex = startIndex + interval + Int(arc4random_uniform(250))
randomInRange(startIndex...penultimateIndex, atMultipleOfInterval: interval)

How to "link" two ranges together in swift

I have a function that produces a random number output (see below). I'd like for it to choose that output from either 0-50 or 150-400, but not in between. I couldn't find much about it on my own... so if any of you could post either resources or an answer that would be awesome! Thanks so much in advance!
The three question marks are where I assume some operator would go.
func random() -> UInt32 {
var range = UInt32(0)...UInt32(50) ??? UInt32(150)...UInt32(400)
return range.startIndex + arc4random_uniform(range.endIndex - range.startIndex + 1)
}
I tried using the + operator and the | operator, but no luck.
You cannot pass a union of ranges to arc4random_uniform().
What you can do is to create a random number in a single interval and then "adjust" all numbers which are not in the first range to the second range:
func random() -> UInt32 {
var x = arc4random_uniform(302) // 0 .. 301
if (x > 50) {
// map 51 .. 301 to 150 .. 400:
x += 99
}
return x
}
This can be generalized to multiple ranges (now updated for Swift 3):
func randomNumber(fromRanges ranges: Range<UInt32>...) -> UInt32 {
let totalLength = ranges.reduce(0) { $0 + ($1.upperBound - $1.lowerBound)}
var rnd = arc4random_uniform(totalLength)
for range in ranges {
if rnd < range.upperBound - range.lowerBound {
return rnd + range.lowerBound
}
rnd -= range.upperBound - range.lowerBound
}
fatalError("this should never be reached")
}
let x = randomNumber(fromRanges: 0 ..< 51, 150 ..< 401)
An alternative to ranges is to just use a while loop to make sure you get a value in the range you want.
func randomFunc() -> UInt32 {
var rand: UInt32 = 401
while rand < 0 || rand > 400 || (rand > 50 && rand < 150){
rand = arc4random_uniform(400)
}
return rand;
}