Arc4random float? - ios

Doing this:
float x = arc4random() % 100;
returns a decent result of a number between 0 and 100.
But doing this:
float x = (arc4random() % 100)/100;
Returns 0. How can I get it to return a float value?

Simply, you are doing integer division, instead of floating point division, so you are just getting a truncated result (.123 is truncated to 0, for example). Try
float x = (arc4random() % 100)/100.0f;

You are dividing an int by an int, which gives an int. You need to cast either to a float:
float x = (arc4random() % 100)/(float)100;
Also see my comment about the modulo operator.

To get a float division instead of an integer division:
float x = arc4random() % 100 / 100.f;
But be careful, using % 100 will only give you a value between 0 and 99, so dividing it by 100.f will only produce a random value between 0.00f and 0.99f.
Better, to get a random float between 0 and 1:
float x = arc4random() % 101 / 100.f;
Even better, to avoid modulus bias:
float x = arc4random_uniform(101) / 100.f;
Alternatively, to avoid a two digits precision bias:
float x = (float)arc4random() / UINT32_MAX;
And in Swift 4.2+, you get built-in support for ranges:
let x = Float.random(in: 0.0...1.0)

In Swift:
Float(arc4random() % 100) / 100

Related

Dynamic values in percentage format in Objective C

I want to know making Objective C variable values in percentage format. I am getting 6 values dynamically. Sometimes values might increase more than 100. For ex: Avalue=143, Bvalue=450, Cvalue=76, Dvalue=98, Evalue=123, Fvalue=56
how can i format each value under percentage format?
(Avalue * 100)/100.f
(Bvalue * 100)/100.f
(Cvalue * 100)/100.f
(Dvalue * 100)/100.f
(Evalue * 100)/100.f
(Fvalue * 100)/100.f
Is this proper way of doing it?
Well, percentage numbers are in essence fractions. In mathematics, a percentage is a number or ratio expressed as a fraction of 100.
if you want to compare numbers like in your case, compare each numbers to the sum oaf all value, then set the sum as 100%.
float sumAllValues = (Avalue + Bvalue + ...);
float aValuePercent = (Avalue / sumAllValues) * 100.f
you can format that percentage number with NSNumberFormatter
NSString *result1 = [NSNumberFormatter localizedStringFromNumber:[NSNumber numberWithFloat:aValuePercent];
numberStyle:NSNumberFormatterPercentStyle];
btw: why the variables begin with a Uppercase?
-Edit-
When you divide integers, keep in mind that integers divided by integer results integer.
I wrote a short example for the console.
NSInteger a = 5;
NSInteger b = 6;
NSInteger c = a * 100 / b;
NSInteger d = a / b * 100;
// example with conversion al values to float
float e = [[NSNumber numberWithInteger:a] floatValue] / [[NSNumber numberWithInteger:b] floatValue] * 100;
NSLog(#"resulting int c: %lu", c);
NSLog(#"resulting int d: %lu", d);
NSLog(#"resulting float e: %f", e);
2017-02-14 19:36:54.897 IntegerTest[2291:1238166] resulting int c: 83
2017-02-14 19:36:54.898 IntegerTest[2291:1238166] resulting int d: 0
2017-02-14 19:36:54.898 IntegerTest[2291:1238166] resulting float e: 83.333328
Program ended with exit code: 0
You see, when you multiply the first integer with 100 and the divide, you get 83.
The other way round (what is mathematically correct), first the division and after the multiply, you get 0, because 5/6 is less than 1 and the integer value is set to 0. Since multiplying 0 by any other value remains 0, the result is 0.
EDIT AGAIN -
the code from console is written with plain integers, but in essence they are the same as your values. First the multiplication, then the division.
NSInteger aPercentage = (Avalue * 100) / Bvalue;
or cast all values to floats. like so:
float aValueFloat = [[NSNumber numberWithInt:Avalue] floatValue];
EDIT AGAIN -
This was only for example reasons. Value is only the divisor because I do not know, to wash value you want to compare those values. In this example Avalue is compared to Bvalue, say Avalue is percent from Bvalue.
If you only want to print out Avlue = 143 in 143% then:
NSInteger aValue = 146;
NSString *aValuePercentString = [NSString stringWithFormat:#"%ld%%", aValue];
NSLog(#"%#", aValuePercentString);
Output: 2017-02-15 16:52:26.346 test[2132:1070601] 146%
Note1: This works with values as Integers. If the values are NSNumbers use %# instead of %ld.
Note2: Value is not an Integer anymore but a string.
Hope it helps!

Adding fractions calculation not working in IOS

I am trying to add fractions to get a value to put in for my progress bar but am just getting 0. here is what I have and what it is logging.
NSLog(#"prog::%f",self.progView.progress);
int total = self.forms.count;
float calc = (float)(self.progView.progress / total) + (1/total);
NSLog(#"calc::%f",calc);
NSLog(#"total::%d",total);
self.progView.progress = calc;
NSLog(#"prog now:%f", self.progView.progress);
Log:
prog::0.000000
calc::0.000000
total::4
prog now:0.000000
Take care of where you place your cast to float. Try changing from this:
float calc = (float)(self.progView.progress / total) + (1/total);
To this:
float calc = ((float)self.progView.progress / (float)total) + (1/(float)total);
Alternatively, make total a float rather than an int, e.g.
float total = self.forms.count;
float calc = ((float)self.progView.progress / total) + (1 / total);

iOS objective-C: using modulo on a float to get "inches" from Feet

I am trying to make a simple objective-C height converter. The input is a (float) variable of feet, and I want to convert to (int) feet and (float) inches:
float totalHeight = 5.122222;
float myFeet = (int) totalHeight; //returns 5 feet
float myInches = (totalHeight % 12)*12; //should return 0.1222ft, which becomes 1.46in
However, I keep getting an error from xcode, and I realized that the modulo operator only works with (int) and (long). Can someone please recommend an alternative method? Thanks!
Even modulo works for float, use :
fmod()
You can use this way too...
float totalHeight = 5.122222;
float myFeet = (int) totalHeight; //returns 5 feet
float myInches = fmodf(totalHeight, myFeet);
NSLog(#"%f",myInches);
Why don't you use
CGFloat myInches = totalHeight - myFeet;
As answered earlier, subtracting is the way to go. Just remember to convert the one tenths of feet to inches by multiplying with 12:
float totalHeight = 5.122222;
int myFeet = (int) totalHeight;
float myInches = (totalHeight - myFeet) * 12;

Generate a random float between 0 and 1

I'm trying to generate a random number that's between 0 and 1. I keep reading about arc4random(), but there isn't any information about getting a float from it. How do I do this?
Random value in [0, 1[ (including 0, excluding 1):
double val = ((double)arc4random() / UINT32_MAX);
A bit more details here.
Actual range is [0, 0.999999999767169356], as upper bound is (double)0xFFFFFFFF / 0x100000000.
// Seed (only once)
srand48(time(0));
double x = drand48();
// Swift version
// Seed (only once)
srand48(Int(Date().timeIntervalSince1970))
let x = drand48()
The drand48() and erand48() functions return non-negative, double-precision, floating-point values, uniformly distributed over the interval [0.0 , 1.0].
For Swift 4.2+ see: https://stackoverflow.com/a/50733095/1033581
Below are recommendations for correct uniformity and optimal precision for ObjC and Swift 4.1.
32 bits precision (Optimal for Float)
Uniform random value in [0, 1] (including 0.0 and 1.0), up to 32 bits precision:
Obj-C:
float val = (float)arc4random() / UINT32_MAX;
Swift:
let val = Float(arc4random()) / Float(UInt32.max)
It's optimal for:
a Float (or Float32) which has a significand precision of 24 bits for its mantissa
48 bits precision (discouraged)
It's easy to achieve 48 bits precision with drand48 (which uses arc4random_buf under the hood). But note that drand48 has flaws because of the seed requirement and also for being suboptimal to randomize all 52 bits of Double mantissa.
Uniform random value in [0, 1], 48 bits precision:
Swift:
// seed (only needed once)
srand48(Int(Date.timeIntervalSinceReferenceDate))
// random Double value
let val = drand48()
64 bits precision (Optimal for Double and Float80)
Uniform random value in [0, 1] (including 0.0 and 1.0), up to 64 bits precision:
Swift, using two calls to arc4random:
let arc4random64 = UInt64(arc4random()) << 32 &+ UInt64(arc4random())
let val = Float80(arc4random64) / Float80(UInt64.max)
Swift, using one call to arc4random_buf:
var arc4random64: UInt64 = 0
arc4random_buf(&arc4random64, MemoryLayout.size(ofValue: arc4random64))
let val = Float80(arc4random64) / Float80(UInt64.max)
It's optimal for:
a Double (or Float64) which has a significand precision of 52 bits for its mantissa
a Float80 which has a significand precision of 64 bits for its mantissa
Notes
Comparisons with other methods
Answers where the range is excluding one of the bounds (0 or 1) likely suffer from a uniformity bias and should be avoided.
using arc4random(), best precision is 1 / 0xFFFFFFFF (UINT32_MAX)
using arc4random_uniform(), best precision is 1 / 0xFFFFFFFE (UINT32_MAX-1)
using rand() (secretly using arc4random), best precision is 1 / 0x7FFFFFFF (RAND_MAX)
using random() (secretly using arc4random), best precision is 1 / 0x7FFFFFFF (RAND_MAX)
It's mathematically impossible to achieve better than 32 bits precision with a single call to arc4random, arc4random_uniform, rand or random. So our above 32 bits and 64 bits solutions should be the best we can achieve.
This function works for negative float ranges as well:
float randomFloat(float Min, float Max){
return ((arc4random()%RAND_MAX)/(RAND_MAX*1.0))*(Max-Min)+Min;
}
Swift 4.2+
Swift 4.2 adds native support for a random value in a Range:
let x = Float.random(in: 0.0...1.0)
let y = Double.random(in: 0.0...1.0)
let z = Float80.random(in: 0.0...1.0)
Doc:
random(in range: ClosedRange<Float>)
random(in range: Range<Float>)
random(in range: ClosedRange<Double>)
random(in range: Range<Double>)
random(in range: ClosedRange<Float80>)
random(in range: Range<Float80>)
(float)rand() / RAND_MAX
The previous post stating "rand()" alone was incorrect.
This is the correct way to use rand().
This will create a number between 0 -> 1
BSD docs:
The rand() function computes a sequence of pseudo-random integers in the
range of 0 to RAND_MAX (as defined by the header file "stdlib.h").
This is extension for Float random number Swift 3.1
// MARK: Float Extension
public extension Float {
/// Returns a random floating point number between 0.0 and 1.0, inclusive.
public static var random: Float {
return Float(arc4random()) / Float(UInt32.max))
}
/// Random float between 0 and n-1.
///
/// - Parameter n: Interval max
/// - Returns: Returns a random float point number between 0 and n max
public static func random(min: Float, max: Float) -> Float {
return Float.random * (max - min) + min
}
}
Swift 4.2
Swift 4.2 has included a native and fairly full-featured random number API in the standard library. (Swift Evolution proposal SE-0202)
let intBetween0to9 = Int.random(in: 0...9)
let doubleBetween0to1 = Double.random(in: 0...1)
All number types have the static random(in:) function which takes the range and returns the random number in the given range.
Use this to avoid problems with upper bound of arc4random()
u_int32_t upper_bound = 1000000;
float r = arc4random_uniform(upper_bound)*1.0/upper_bound;
Note that it is applicable for MAC_10_7, IPHONE_4_3 and higher.
arc4random has a range up to 0x100000000 (4294967296)
This is another good option to generate random numbers between 0 to 1:
srand48(time(0)); // pseudo-random number initializer.
double r = drand48();
float x = arc4random() % 11 * 0.1;
That produces a random float bewteen 0 and 1.
More info here
rand()
by default produces a random number(float) between 0 and 1.

Objective-C Random Numbers

I'm making a simple pong game. To make the ball move at the beginning of a new round, I am using
ballVelocity = CGPointMake(4 - arc4random() % 8,4 - arc4random() % 8);
However, the important part is just this:
4 - arc4random() % 8
However, there are a few problems with this: first and foremost, it doesn't really generate a random number. Only after I quit the simulator, then reopen it are new numbers generated. Secondly, I only want it to generate numbers between -4 and -2 or 2 and 4.
arc4random() is the preferred random function on the iphone, instead of rand(). arc4random() does not need seeding.
This code will generate the ranges you're interested in:
int minus2_to_minus4 = (arc4random() % 3) - 4;
int two_to_four = (arc4random() % 3) + 2;
You need to look at the rand() function. Basically, you "seed" it with a start value, and it returns a new random number every time you call it.
Or look at this question which has a full example using arc4random.
This will give you a floating point number between -4 and -2 OR 2 and 4
float low_bound = -4; //OR 2
float high_bound = -2;//OR 4
float rndValue = (((float)arc4random()/0x100000000)*(high_bound-low_bound)+low_bound);
If you want a number in -4…-2 AND 2…4 try this:
float low_bound = 2;
float high_bound = 4;
float rndValueTemp = (((float)arc4random()/0x100000000)*(high_bound-low_bound)+low_bound);
float rndValue = ((float)arc4random()/0x100000000)<0.5?-rndValueTemp:rndValueTemp;

Resources