I'm making a game and I've been trying to produce random movement. This is my code.
let actualDuration = NSTimeInterval(random(min(): CGFloat(3.0), max: CGFloat(4.0)))
The min and max aren't working please help.
Unlike the .NET Framework or the JDK, there isn't a function that takes min and max parameters to generate a random number. :(
If you want to generate a random number between 3 and 4, you should use the arc4random_uniform function to generate a number between 0 and 999 first and then divide that number by 1000 and plus 3:
let randomNumber = Double(arc4random_uniform(1000))
let actualDuration = CGFloat(randomNumber / 1000 + 3)
Let me explain how this works.
randomNumber is between 0 and 999 right? Now when you divide it by 1000, it becomes a number less than 1. i.e. 0 ~ 0.999. And you add this number to 3, the result becomes a random number between 3 and 4, which is what you wanted.
If you want a more precise double, you can generate a number between 0 and 9999 and divide it by 10000. You know what I mean!
#Ethan Marcus
try like this
let minValue = 3
let maxValue = 4
let actualDuration = NSTimeInterval(minValue + (random() % (maxValue - minValue)))
Related
This question might seem a bit silly..:) But I think I'm missing something somewhere..so bit confused...
I wanted to generate all numbers from 0 to 1. In other words, if I do 1/2, I get 0.5. Then 0.5/2 = 0.25. Then 0.25/2 = 0.125. This will go on until 0.00000001 (A total of 26 divisions)
But I want to generate all numbers in an increasing order from 0.00000001 to 1.
I tried doing something like so...
let first = 0.00000001
let last = 1.0
let interval = first * 2
let sequence = stride(from: first, to: last, by: interval)
for element in sequence {
print(element)
}
But it's not working. It seemed it just prints infinitely...
How can I properly use a for loop and print from 0.00000001 to 1 in a limited number of iterations..? Or any other loops to be used in this case..?
You can't use stride. stride produces an arithmetic sequence with a difference of interval, which is 0.00000002:
0.00000001
0.00000003
0.00000005
0.00000007
...
You want a geometric sequence between 0 and 1.
You could use sequence instead, which generates an infinite sequence:
let first = 0.00000001
let last = 1.0
for item in sequence(first: first, next: { $0 * 2 }).prefix(while: { $0 < last }) {
print(item)
}
{ $0 * 2 } is the function that generates the next element, and prefix(while:) is used to get first elements that satisfy the < last condition.
Here is another way you could approach it. Use stride to count down the powers of 2 from 26 to 0 and divide 1.0 by that power of 2 and display only the first 8 decimal places:
for n in stride(from: 26, through: 0, by: -1) {
print(String(format: "%.8f", 1.0 / pow(2.0, Double(n))))
}
or equivalently (removing the 1/n by using negative exponents):
for n in -26...0 {
print(String(format: "%.8f", pow(2.0, Double(n))))
}
Output:
0.00000001
0.00000003
0.00000006
0.00000012
0.00000024
0.00000048
0.00000095
0.00000191
0.00000381
0.00000763
0.00001526
0.00003052
0.00006104
0.00012207
0.00024414
0.00048828
0.00097656
0.00195312
0.00390625
0.00781250
0.01562500
0.03125000
0.06250000
0.12500000
0.25000000
0.50000000
1.00000000
I get the following error when using code for an extension, I'm not sure if they're asking to just use a different operator or modify the values in the expression based on an internet search.
Error: % is unavailable: Use truncatingRemainder instead
Extension code:
extension CMTime {
var durationText:String {
let totalSeconds = CMTimeGetSeconds(self)
let hours:Int = Int(totalSeconds / 3600)
let minutes:Int = Int(totalSeconds % 3600 / 60)
let seconds:Int = Int(totalSeconds % 60)
if hours > 0 {
return String(format: "%i:%02i:%02i", hours, minutes, seconds)
} else {
return String(format: "%02i:%02i", minutes, seconds)
}
}
}
The error(s) occur when setting the minutes and seconds variables.
CMTimeGetSeconds() returns a floating point number (Float64 aka
Double). In Swift 2 you could compute the
remainder of a floating point division as
let rem = 2.5 % 1.1
print(rem) // 0.3
In Swift 3 this is done with
let rem = 2.5.truncatingRemainder(dividingBy: 1.1)
print(rem) // 0.3
Applied to your code:
let totalSeconds = CMTimeGetSeconds(self)
let hours = Int(totalSeconds / 3600)
let minutes = Int((totalSeconds.truncatingRemainder(dividingBy: 3600)) / 60)
let seconds = Int(totalSeconds.truncatingRemainder(dividingBy: 60))
However, in this particular case it is easier to convert the duration
to an integer in the first place:
let totalSeconds = Int(CMTimeGetSeconds(self)) // Truncate to integer
// Or:
let totalSeconds = lrint(CMTimeGetSeconds(self)) // Round to nearest integer
Then the next lines simplify to
let hours = totalSeconds / 3600
let minutes = (totalSeconds % 3600) / 60
let seconds = totalSeconds % 60
The % modulus operator is defined only for integer types. For floating-point types, you need to be more specific about the kind of IEEE 754 division/remainder behavior you want, so you have to call a method: either remainder or truncatingRemainder. (If you're doing floating-point math you actually need to care about this, and lots of other stuff, or you can get unexpected / bad results.)
If you actually intend to do integer modulus, you need to convert the return value of CMTimeGetSeconds to an integer before using %. (Note that if you do, you'll lop off the fractional seconds... depending on where you're using CMTime that may be important. Do you want minutes:seconds:frames, for example?)
Depending on how you want to present CMTime values in your UI, it might be better to extract the seconds value and pass it to NSDateFormatter or NSDateComponentsFormatter so you get appropriate locale support.
Bring back the simple modulo syntax in swift 3:
This syntax was actually suggested on Apples official swift mailing list here but for some reason they opted for a less elegant syntax.
infix operator %%/*<--infix operator is required for custom infix char combos*/
/**
* Brings back simple modulo syntax (was removed in swift 3)
* Calculates the remainder of expression1 divided by expression2
* The sign of the modulo result matches the sign of the dividend (the first number). For example, -4 % 3 and -4 % -3 both evaluate to -1
* EXAMPLE:
* print(12 %% 5) // 2
* print(4.3 %% 2.1) // 0.0999999999999996
* print(4 %% 4) // 0
* NOTE: The first print returns 2, rather than 12/5 or 2.4, because the modulo (%) operator returns only the remainder. The second trace returns 0.0999999999999996 instead of the expected 0.1 because of the limitations of floating-point accuracy in binary computing.
* NOTE: Int's can still use single %
* NOTE: there is also .remainder which supports returning negatives as oppose to truncatingRemainder (aka the old %) which returns only positive.
*/
public func %% (left:CGFloat, right:CGFloat) -> CGFloat {
return left.truncatingRemainder(dividingBy: right)
}
This simple swift 3 migration tip is part of a more comprehensive swift 3 migration guide with many insights (35k loc / 8-days of migration) http://eon.codes/blog/2017/01/12/swift-3-migration/
There's no need to create a separate modulo operator for floating point numbers, unless you think it makes the code safer. You can overload the % operator to accept floating point numbers like so:
func %<N: BinaryFloatingPoint>(lhs: N, rhs: N) -> N {
lhs.truncatingRemainder(dividingBy: rhs)
}
Usage
let a: Float80 = 10
let b: Float80 = 3
print(a % b)
You can now use % with any two floating point numbers of the same tye.
I found that the following works in Swift 3:
let minutes = Int(floor(totalSeconds / 60))
let seconds = Int(totalSeconds) % 60
where totalSeconds is a TimeInterval (Double).
i want to generate a series of number through looping.
my series will contain numbers like 0,3,5,8,10,13,15,18 and so on.
i try to take reminder and try to add 2 and 3 but it wont work out.
can any one please help me in generating this series.
You can just use an increment which toggles between 3 and 2, e.g.
for (i = 0, inc = 3; i < 1000; i += inc, inc = 5 - inc)
{
printf("%d\n", i);
}
It looks like the the sequence starts at zero, and uses increments of 3 and 2. There are several ways of implementing this, but perhaps the simplest one would be iterating in increments of 5 (i.e. 3+2) and printing two numbers - position and position plus three.
Here is some pseudocode:
i = 0
REPEAT N times :
PRINT i
PRINT i + 3
i += 5
The iteration i=0 will print 0 and 3
The iteration i=5 will print 5 and 8
The iteration i=10 will print 10 and 13
The iteration i=15 will print 15 and 18
... and so on
I was pulled in with the tag generate-series, which is a powerful PostgreSQL function. This may have been tagged by mistake (?) but it just so happens that there would be an elegant solution:
SELECT ceil(generate_series(0, 1000, 25) / 10.0)::int;
generate_series() returns 0, 25, 50, 75 , ... (can only produces integer numbers)
division by 10.0 produces numeric data: 0, 2.5, 5, 7.5, ...
ceil() rounds up to your desired result.
The final cast to integer (::int) is optional.
SQL Fiddle.
Consider the following code:
let dl = 9.5 / 11.
let min = 21.5 + dl
let max = 40.5 - dl
let a = [ for z in min .. dl .. max -> z ] // should have 21 elements
let b = a.Length
"a" should have 21 elements but has got only 20 elements. The "max - dl" value is missing. I understand that float numbers are not precise, but I hoped that F# could work with that. If not then why F# supports List comprehensions with float iterator? To me, it is a source of bugs.
Online trial: http://tryfs.net/snippets/snippet-3H
Converting to decimals and looking at the numbers, it seems the 21st item would 'overshoot' max:
let dl = 9.5m / 11.m
let min = 21.5m + dl
let max = 40.5m - dl
let a = [ for z in min .. dl .. max -> z ] // should have 21 elements
let b = a.Length
let lastelement = List.nth a 19
let onemore = lastelement + dl
let overshoot = onemore - max
That is probably due to lack of precision in let dl = 9.5m / 11.m?
To get rid of this compounding error, you'll have to use another number system, i.e. Rational. F# Powerpack comes with a BigRational class that can be used like so:
let dl = 95N / 110N
let min = 215N / 10N + dl
let max = 405N / 10N - dl
let a = [ for z in min .. dl .. max -> z ] // Has 21 elements
let b = a.Length
Properly handling float precision issues can be tricky. You should not rely on float equality (that's what list comprehension implicitely does for the last element). List comprehensions on float are useful when you generate an infinite stream. In other cases, you should pay attention to the last comparison.
If you want a fixed number of elements, and include both lower and upper endpoints, I suggest you write this kind of function:
let range from to_ count =
assert (count > 1)
let count = count - 1
[ for i = 0 to count do yield from + float i * (to_ - from) / float count]
range 21.5 40.5 21
When I know the last element should be included, I sometimes do:
let a = [ for z in min .. dl .. max + dl*0.5 -> z ]
I suspect the problem is with the precision of floating point values. F# adds dl to the current value each time and checks if current <= max. Because of precision problems, it might jump over max and then check if max+ε <= max (which will yield false). And so the result will have only 20 items, and not 21.
After running your code, if you do:
> compare a.[19] max;;
val it : int = -1
It means max is greater than a.[19]
If we do calculations the same way the range operator does but grouping in two different ways and then compare them:
> compare (21.5+dl+dl+dl+dl+dl+dl+dl+dl) ((21.5+dl)+(dl+dl+dl+dl+dl+dl+dl));;
val it : int = 0
> compare (21.5+dl+dl+dl+dl+dl+dl+dl+dl+dl) ((21.5+dl)+(dl+dl+dl+dl+dl+dl+dl+dl));;
val it : int = -1
In this sample you can see how adding 7 times the same value in different order results in exactly the same value but if we try it 8 times the result changes depending on the grouping.
You're doing it 20 times.
So if you use the range operator with floats you should be aware of the precision problem.
But the same applies to any other calculation with floats.
Can I set a range of numbers when using arc4random()? For example 50-100 only.
As pointed out in other posts below, it is better to use arc4random_uniform. (When this answer was originally written, arc4random_uniform was not available). Besides avoiding the modulo bias of arc4random() % x, it also avoids a seeding problem with arc4random when used recursively in short timeframes.
arc4random_uniform(4)
will generate 0, 1, 2 or 3. Thus you could use:
arc4random_uniform(51)
and merely add 50 to the result to get a range between 50 & 100 (inclusive).
To expand upon JohnK comment.
It is suggested that you use the following function to return a ranged random number:
arc4random_uniform(51)
which will return a random number in the range 0 to 50.
Then you can add your lower bounds to this like:
arc4random_uniform(51) + 50
which will return a random number in the range 50 to 100.
The reason we use arc4random_uniform(51) over arc4random() % 51 is to avoid the modulo bias. This is highlighted in the man page as follows:
arc4random_uniform(upper_bound) will return a uniformly distributed random number less than upper_bound. arc4random_uniform() is recommended over constructions like ``arc4random() % upper_bound'' as it avoids "modulo bias" when the upper bound is not a power of two.
In short you get a more evenly distributed random number generated.
int fromNumber = 10;
int toNumber = 30;
int randomNumber = (arc4random()%(toNumber-fromNumber))+fromNumber;
Will generate randon number between 10 and 30, i.e. 11,12,13,14......29
You can use this code for generating random values with range:
//range from 50 to 100
int num1 = (arc4random() % 50) + 50; or
int num1 = arc4random_uniform(50) + 50;
//range from 0-100
int num1 = arc4random() % 100; or
int num1 = arc4random_uniform(100);
In Swift you can use this (inspired by answer of #Justyn)
func generateRandomKey(fromRange rangeFrom:Int, toRange rangeTo:Int) -> Int{
let theKey = arc4random_uniform(UInt32(rangeTo - rangeFrom)) + UInt32(rangeFrom)
return Int(theKey)
}
Will always give you a random range Integer.
In many situations 10 thru 30 would mean inclusive, (includes 10 and 30) ...
int fromNumber = 10;
int toNumber = 30;
toNumber ++;
int randomNumber = (arc4random()%(toNumber-fromNumber))+fromNumber;
Notice the difference toNumber - fromNumber is now 21 ... (20+1) which yields the possible results of 0 thru 20 (inclusive) which when added to fromNumber (10) results in 10 thru 30 (inclusive).