What is the Modulo function for negative decimals Objective-C? - objective-c

I need to calculate modulos with decimals that can be negative as well
for example: fmod( -5.2, 3 );
while mod() works with integers, and fmod() (or fmodf()) works well with decimals, fmod() returns wrong results with negative decimals:
ex:
double modulo = fmod (5.2, 3);
NSLog (#"==> %f", modulo);
==> 2.2 // This is correct !!
double modulo = fmod (-5.2, 3);
NSLog (#"==> %f", modulo);
==> -2.2 // This is wrong !! should be 0.8
Is there another mod() in the library or should i write my own decimal negative mod function ?
something like :
if (res = fmod(x,m) < 0) {
res+=m;
}
Thx !

-2.2 is correct and is also -5.2 mod 3. The fmod function is a C function (and therefore also Objective C), so you can find more detail about it by typing man fmod into terminal. When doing fmod it will preserve the sign of the value that you are moding. So to get the mod you want, you will need to check the sign (of either the result, or the value you are passing in) and if it is negative you will need to add the modulo base, in this case 3.
This is the definition of the fmod function:
double
fmod(double x, double y);
Specifically, the functions return the value x-i*y, for some integer i such that, if y is non-zero, the result has the same sign as x and magnitude less than the magnitude of y.
from the OS X man page.

For your purposes, you can do something like this:
#include <math.h>
float f_mod(float a, float n) {
return a - n * floor(a / n);
}
Of course, be careful to check n>0.
f_mod(-5.2f, 2.0f) = 0.8
f_mod(5.2f, 2.0f) = 2.2

Thank you so i ended up writing a wrapper... What i was hopping i could avoid. This works great for me, and, in my opinion, represents the correct mathematical definition of the modulo (not the C implementation). I am sure this function can be optimized,but for clarity i leave it this way:
//--
//-- Modulo
//--
double calcModulo ( double x, double m) {
double res = INFINITY;
if (m==0)
return res ;
double posMod, negMod, posM, posX;
posM = m < 0 ? -m:m;
posX = x < 0 ? -x:x;
posMod = fmod (posX, posM);
negMod = fmod (-posX,posM) + posM;
// pick up the correct res
if ( x >= 0 ){
if (m > 0) {
res = posMod;
} else {
res = -negMod;
}
}else{
if (m > 0) {
res= negMod;
} else{
res= -posMod;
}
}
return res;
}

Related

Mean or Sum of objective function matters in optimization?

I'm using RcppEnsmallen to estimate quantile regression models. I think I have set up everything right, but problems have been constantly emerging. I've tried two strategies:
Strategy 1: in the objective function, return sum of all errors. The corresponding gradient setup is similar. I tried 0.1 quantile in my example. However, occasionally I can get correct answers. Most of the time, it returns NaN.
Strategy 2: The objective function changed to mean of the sum of all errors. The gradient setup is also use the mean version. However, in this scenario, it returns quite different values each time, far from the correct answers.
I was wondering where the problem might be? Thanks.
#include <RcppEnsmallen.h>
// [[Rcpp::depends(RcppEnsmallen)]]
class QuantileRegressionFunction
{
public:
// Construct the QuantileRegressFunction with the given data.
QuantileRegressionFunction(const arma::mat& X,
const arma::colvec& y
) : X(X),y(y){}
// Define the objective function.
double Evaluate(const arma::mat& beta){
// arma::vec residual1 = y - X * beta;
return arma::sum( (y - X * beta) % ( 0.1 - arma::ones(y.n_rows) % ( (y - X * beta) <0 )) );
}
void Gradient(const arma::mat& beta, arma::mat& gradient)
{
gradient = -X.t() * ( 0.1 - arma::ones(y.n_rows) % ( (y - X * beta) <0 ) ) ;
}
private:
const arma::mat& X;
const arma::vec& y;
};
// [[Rcpp::export]]
arma::mat qr_reg(const arma::mat&X, const arma::vec&y){
QuantileRegressionFunction qrf(X,y);
ens::L_BFGS lbfgs;
lbfgs.MaxIterations()= 100000 ;
lbfgs.MaxLineSearchTrials() = 10000;
//lbfgs.ArmijoConstant() = 1e-10;
arma::mat beta(X.n_cols, 1 , arma::fill::randn);
lbfgs.Optimize(qrf,beta);
return beta;
}

Generate a random double between 1 and max in c++/cli

How would i generate a random double between 1 and a defined max in c++/cli, ive use random_number_distribution and mersenne twister in the random header before but never in cli, will this work in cli with random or system::random, or are there any similar alternatives? Thanks.
Here's how
double randDouble(double fMin, double fMax)
{
double f = (double)rand() / RAND_MAX;
return fMin + f * (fMax - fMin);
}
The System::Random class, with its NextDouble method is what you want. NextDouble will return a double >= 0.0 and < 1.0. So, to return a value between 1 and a max:
double RandOneToMax(double max)
{
Random^ r = ...;
return (r->NextDouble() * (max - 1)) + 1;
}

nan double in objective c

I have this equation
double x = ((newCount/allCount)/.8)*5.0;
newCount is a double with value 0
allCount is a double with value 0
the result of x is -nan(0x8000000000000)
why this happens and how to check this value in objective c to assign default value for it
You are diving by zero. You can check for it using:
isnan(x)
The problem is that the denominator (allCount) is 0; dividing by zero is not allowed and the answer is not a number. The simplest thing you could do is to test for that before doing the division:
if (allCount != 0) {
x = ((newCount/allCount)/.8)*5.0
} else {
x = defaultValue;
}
There are more complicated ways using C's floating point environment and testing for the FE_DIVBYZERO exception, but while that's standard it's rarely used and therefore potentially more difficult for a later reader of the code to comprehend.
allCount is a 0, thus you just divided by 0 (which is impossible if you didn't know..) So before you assign x, just make sure that allCount is not 0 first.
if (allCount != 0)
double x = ((newCount/allCount)/.8)*5.0;

Generate Random Numbers Between Two Numbers in Objective-C

I have two text boxes and user can input 2 positive integers (Using Objective-C). The goal is to return a random value between the two numbers.
I've used "man arc4random" and still can't quite wrap my head around it. I've came up with some code but it's buggy.
float lowerBound = lowerBoundNumber.text.floatValue;
float upperBound = upperBoundNumber.text.floatValue;
float rndValue;
//if lower bound is lowerbound < higherbound else switch the two around before randomizing.
if(lowerBound < upperBound)
{
rndValue = (((float)arc4random()/0x100000000)*((upperBound-lowerBound)+lowerBound));
}
else
{
rndValue = (((float)arc4random()/0x100000000)*((lowerBound-upperBound)+upperBound));
}
Right now if I put in the values 0 and 3 it seems to work just fine. However if I use the numbers 10 and 15 I can still get values as low as 1.0000000 or 2.000000 for "rndValue".
Do I need to elaborate my algorithm or do I need to change the way I use arc4random?
You could simply use integer values like this:
int lowerBound = ...
int upperBound = ...
int rndValue = lowerBound + arc4random() % (upperBound - lowerBound);
Or if you mean you want to include float number between lowerBound and upperBound? If so please refer to this question: https://stackoverflow.com/a/4579457/1265516
The following code include the minimum AND MAXIMUM value as the random output number:
- (NSInteger)randomNumberBetween:(NSInteger)min maxNumber:(NSInteger)max
{
return min + arc4random_uniform((uint32_t)(max - min + 1));
}
Update:
I edited the answer by replacing arc4random() % upper_bound with arc4random_uniform(upper_bound) as #rmaddy suggested.
And here is the reference of arc4random_uniform for the details.
Update2:
I updated the answer by inserting a cast to uint32_t in arc4random_uniform() as #bicycle indicated.
-(int) generateRandomNumberWithlowerBound:(int)lowerBound
upperBound:(int)upperBound
{
int rndValue = lowerBound + arc4random() % (upperBound - lowerBound);
return rndValue;
}
You should avoid clamping values with mod (%) if you can, because even if the pseudo-random number generator you're using (like arc4random) is good at providing uniformly distributed numbers in its full range, it may not provide uniformly distributed numbers within the restricted modulo range.
You also don't need to use a literal like 0x100000000 because there is a convenient constant available in stdint.h:
(float)arc4random() / UINT32_MAX
That will give you a random float in the interval [0,1]. Note that arc4random returns an integer in the interval [0, 2**32 - 1].
To move this into the interval you want, you just add your minimum value and multiply the random float by the size of your range:
lowerBound + ((float)arc4random() / UINT32_MAX) * (upperBound - lowerBound);
In the code you posted you're multiplying the random float by the whole mess (lowerBound + (upperBound - lowerBound)), which is actually just equal to upperBound. And that's why you're still getting results less than your intended lower bound.
Objective-C Function:
-(int)getRandomNumberBetween:(int)from to:(int)to
{
return (int)from + arc4random() % (to-from+1);
}
Swift:
func getRandomNumberBetween(_ from: Int, to: Int) -> Int
{
return Int(from) + arc4random() % (to - from + 1)
}
Call it anywhere by:
int OTP = [self getRandomNumberBetween:10 to:99];
NSLog(#"OTP IS %ld",(long)OTP);
NSLog(#"OTP IS %#",[NSString stringWithFormat #"%ld",(long)OTP]);
For Swift:
var OTP: Int = getRandomNumberBetween(10, to: 99)
In Swift:
let otp = Int(arc4random_uniform(6))
Try this.

Rounding with significant digits

In Xcode /Objective-C for the iPhone.
I have a float with the value 0.00004876544. How would I get it to display to two decimal places after the first significant number?
For example, 0.00004876544 would read 0.000049.
I didn't run this through a compiler to double-check it, but here's the basic jist of the algorithm (converted from the answer to this question):
-(float) round:(float)num toSignificantFigures:(int)n {
if(num == 0) {
return 0;
}
double d = ceil(log10(num < 0 ? -num: num));
int power = n - (int) d;
double magnitude = pow(10, power);
long shifted = round(num*magnitude);
return shifted/magnitude;
}
The important thing to remember is that Objective-C is a superset of C, so anything that is valid in C is also valid in Objective-C. This method uses C functions defined in math.h.