Simplifying a fraction with decimals for ratio calculation [duplicate] - objective-c

As part of a calculator app, I am trying to implement uses with sigma notation. However, the result it prints out is always a decimal, and the rest isn't important. I simply want to change the decimal to a fraction.
I already have the reduce function, the problem I'm having is getting from a decimal like this: '0.96875' to it's fractional value, '31/32'
Thanks!
PS: I've looked into just about everything, and for the life of me, I can't figure this out. All I need at this point is how to take the decimal out of it, and I can then reduce it.
Here is my reduce method:
-(void)reduce {
int u = numerator;
int v = denominator;
int temp;
while (v != 0) {
temp = u % v;
u = v;
v = temp;
}
numerator /= u;
denominator /= u;
}

Found this out myself. What I did was multiply the numerator and denominator by 1000000 (recalling that the decimal looked like .96875/1) so that it looked like 96875/100000.
Then, I used this reduce method to bring it into lowest terms:
-(void)reduce {
int u = numerator;
int v = denominator;
int temp;
while (v != 0) {
temp = u % v;
u = v;
v = temp;
}
numerator /= u;
denominator /= u;
}
And finally,I used a print method to get it into fraction form:
//In the .h
#property int numerator, denominator, mixed;
-(void)print;
//In the .m
#synthesize numerator, denominator, mixed;
-(void)print {
if (numerator > denominator) {
//Turn fraction into mixed number
mixed = numerator/denominator;
numerator -= (mixed * denominator);
NSLog(#"= %i %i/%i", mixed, numerator, denominator);
} else if (denominator != 1) {
//Print fraction normally
NSLog(#"= %i/%i", numerator, denominator);
} else {
//Print as integer if it has a denominator of 1
NSLog(#"= %i", numerator);
}
}
And got my desired output:
31/32

I found a fairly good way of doing this a while back, although I don't recall where from. Anyway, it works recursively like this (this is pseudocode, not C):
function getRational(float n)
let i = floor(n); (the integer component of n)
let j = n - i;
if j < 0.0001 (use abritrary precision threshold here), return i/1
let m/n = getRational(1 / j)
return ((i * m) + n) / m
For example, take 3.142857 as a starting point.
i = 3
j = 0.142857
m/n = getRational(7)
i = 7
j = 0
return 7/1
m/n = 7/1
return ((3*7)+1) / 7 = 22/7
Or a more complicated example, 1.55:
i = 1
j = 0.55
m/n = getRational(1.81818181)
i = 1
j = 0.81818181
m/n = getRational(1.22222222)
i = 1
j = 0.22222222
m/n = getRational(4.5)
i = 4
j = 0.5
m/n = getRational(2)
i = 2
j = 0
return 2/1
m/n = 2/1
return ((4*2)+1)/2 = 9/2
m/n = 9/2
return ((1*9)+2)/9 = 11/9
m/n = 11/9
return ((1*11)+9)/11) = 20/11
m/n = 20/11
return ((1*20)+11)/20 = 31/20
I tried this with PI once. It would have gone on a while, but if you set your threshold to 0.01, it only goes down a few recursions before returning 355/113.
There's a bit of a gotcha that you might end up with integers that are too large if it goes down too deep when it returns; I haven't really looked into a good way of allowing for that, except setting the precision threshold to something fairly lax, such as 0.01.

Try this :
-(NSString *)convertToFraction:(CGFloat)floatValue{
double tolerance = 1.0E-6;
CGFloat h1 = 1;
CGFloat h2 = 0;
CGFloat k1 = 0;
CGFloat k2 = 1;
CGFloat b = floatValue;
do{
CGFloat a = floor(b);
CGFloat aux = h1;
h1 = a*h1+h2;
h2 = aux;
aux = k1;
k1 = a*k1+k2;
k2 = aux;
b = 1/(b-a);
}while (ABS(floatValue-h1/k1) > floatValue*tolerance) ;
return k1 > 1 ? [NSString stringWithFormat:#"%.0f/%.0f",h1,k1] : [NSString stringWithFormat:#"%.0f",h1];
}

Related

How to pass a pointer argument to a function without knowing the size to be allocated for that pointer

I know this question is very noob. I am trying to understand how the pointer thing works. I studied basics of C but still did not understand this.
Given this piece of function:
+ (void)nv21ToRgbWithWidth:(unsigned int)width height:(unsigned int)height yuyv:(unsigned char *)yuyv rgb:(unsigned char *)rgb
{
const int nv_start = width * height ;
UInt32 i, j, index = 0, rgb_index = 0;
UInt8 y, u, v;
int r, g, b, nv_index = 0;
for(i = 0; i < height ; i++)
{
for(j = 0; j < width; j ++){
//nv_index = (rgb_index / 2 - width / 2 * ((i + 1) / 2)) * 2;
nv_index = i / 2 * width + j - j % 2;
y = yuyv[rgb_index];
u = yuyv[nv_start + nv_index ];
v = yuyv[nv_start + nv_index + 1];
r = y + (140 * (v-128))/100; //r
g = y - (34 * (u-128))/100 - (71 * (v-128))/100; //g
b = y + (177 * (u-128))/100; //b
if(r > 255) r = 255;
if(g > 255) g = 255;
if(b > 255) b = 255;
if(r < 0) r = 0;
if(g < 0) g = 0;
if(b < 0) b = 0;
index = rgb_index % width + (height - i - 1) * width;
rgb[index * 3+0] = b;
rgb[index * 3+1] = g;
rgb[index * 3+2] = r;
rgb_index++;
}
}
}
How am I suppose to know how the unsigned char * for rgb should be initialized before passing in to the function?
I tried calling the function like this:
unsigned char *rgb = NULL;
[MyClass nv21ToRgbWithWidth:imageWidth height:imageHeight yuyv:yuyvValues rgb:rgb];
But the the program crashes on this line:
rgb[index * 3+0] = b;
I see rgb was initialized with NULL, so you can't assign values. So, I thought of initializing an array and pass it to pointer rgb like this:
unsigned char rgbArr[10000];
unsigned char *rgb = rgbArr;
but the function still crashes. I really don't know how should I pass the rgb parameter in this function. Please help me understand this.
The expected size in bytes seems to be at least height*width*3; it might be that allocating such an array as a local variable (as you do with unsigned char rgbArr[10000]) exceeds a stack limit; The program likely crashes in such a case. I'd try to use the heap instead:
unsigned char* rgb = malloc(imageHeight*imageWidth*3);
[MyClass nv21ToRgbWithWidth:imageWidth height:imageHeight yuyv:yuyvValues rgb:rgb];
...
free(rgb);
That is what the malloc(), calloc(), realloc() and free() functions are for. Don't forget to use the free() function to prevent memory leaks... I hope that helps.

Unable to calculate the sum of prime numbers below 2 million

I'm doing the Euler's Method project to find the sum of prime numbers below 2 million and I'm struggling. Here is the code I'm using. When I calculate the sum below 10 and the sum below 50 I'm getting the right value, but where I'm calculating the sum below 2 million project Euler is saying my solution is incorrect. Any ideas?
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[])
{
#autoreleasepool {
int p = 2, d, total;
BOOL isPrime;
total = 0;
NSLog(#"%i ", p);
for ( p = 3; p < 2e6; p += 2){
isPrime = YES;
for ( d = 3; isPrime == YES && d < p; d += 2)
if ( p % d == 0)
isPrime = NO;
if (isPrime == YES){
NSLog(#"%i ", p);
total += p ;}
}
NSLog(#"total = %i", total + 2);
}
return 0;
}
This function sums the primes less than n using the Sieve of Eratosthenes:
function sumPrimes(n)
sum := 0
sieve := makeArray(2..n, True)
for p from 2 to n step 1
if sieve[p]
sum := sum + p
for i from p * p to n step p
sieve[i] := False
return sum
I'll leave it to you to translate to Objective-C with a suitable data type. For n = 2000000, this should run in one or two seconds.
There are a couple of mistakes. The first being that you're overflowing. Use a long instead of an int. The second thing is just a performance boost. Change your for loop from p < 2e6, to p*p <= 2e6. This way you rule out all numbers above the square root of 2e6. Fix those problems and you'll be good to go. Good luck!

2nd order IIR filter, coefficients for a butterworth bandpass (EQ)?

Important update: I already figured out the answers and put them in this simple open-source library: http://bartolsthoorn.github.com/NVDSP/ Check it out, it will probably save you quite some time if you're having trouble with audio filters in IOS!
^
I have created a (realtime) audio buffer (float *data) that holds a few sin(theta) waves with different frequencies.
The code below shows how I created my buffer, and I've tried to do a bandpass filter but it just turns the signals to noise/blips:
// Multiple signal generator
__block float *phases = nil;
[audioManager setOutputBlock:^(float *data, UInt32 numFrames, UInt32 numChannels)
{
float samplingRate = audioManager.samplingRate;
NSUInteger activeSignalCount = [tones count];
// Initialize phases
if (phases == nil) {
phases = new float[10];
for(int z = 0; z <= 10; z++) {
phases[z] = 0.0;
}
}
// Multiple signals
NSEnumerator * enumerator = [tones objectEnumerator];
id frequency;
UInt32 c = 0;
while(frequency = [enumerator nextObject])
{
for (int i=0; i < numFrames; ++i)
{
for (int iChannel = 0; iChannel < numChannels; ++iChannel)
{
float theta = phases[c] * M_PI * 2;
if (c == 0) {
data[i*numChannels + iChannel] = sin(theta);
} else {
data[i*numChannels + iChannel] = data[i*numChannels + iChannel] + sin(theta);
}
}
phases[c] += 1.0 / (samplingRate / [frequency floatValue]);
if (phases[c] > 1.0) phases[c] = -1;
}
c++;
}
// Normalize data with active signal count
float signalMulti = 1.0 / (float(activeSignalCount) * (sqrt(2.0)));
vDSP_vsmul(data, 1, &signalMulti, data, 1, numFrames*numChannels);
// Apply master volume
float volume = masterVolumeSlider.value;
vDSP_vsmul(data, 1, &volume, data, 1, numFrames*numChannels);
if (fxSwitch.isOn) {
// H(s) = (s/Q) / (s^2 + s/Q + 1)
// http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt
// BW 2.0 Q 0.667
// http://www.rane.com/note170.html
//The order of the coefficients are, B1, B2, A1, A2, B0.
float Fs = samplingRate;
float omega = 2*M_PI*Fs; // w0 = 2*pi*f0/Fs
float Q = 0.50f;
float alpha = sin(omega)/(2*Q); // sin(w0)/(2*Q)
// Through H
for (int i=0; i < numFrames; ++i)
{
for (int iChannel = 0; iChannel < numChannels; ++iChannel)
{
data[i*numChannels + iChannel] = (data[i*numChannels + iChannel]/Q) / (pow(data[i*numChannels + iChannel],2) + data[i*numChannels + iChannel]/Q + 1);
}
}
float b0 = alpha;
float b1 = 0;
float b2 = -alpha;
float a0 = 1 + alpha;
float a1 = -2*cos(omega);
float a2 = 1 - alpha;
float *coefficients = (float *) calloc(5, sizeof(float));
coefficients[0] = b1;
coefficients[1] = b2;
coefficients[2] = a1;
coefficients[3] = a2;
coefficients[3] = b0;
vDSP_deq22(data, 2, coefficients, data, 2, numFrames);
free(coefficients);
}
// Measure dB
[self measureDB:data:numFrames:numChannels];
}];
My aim is to make a 10-band EQ for this buffer, using vDSP_deq22, the syntax of the method is:
vDSP_deq22(<float *vDSP_A>, <vDSP_Stride vDSP_I>, <float *vDSP_B>, <float *vDSP_C>, <vDSP_Stride vDSP_K>, <vDSP_Length __vDSP_N>)
See: http://developer.apple.com/library/mac/#documentation/Accelerate/Reference/vDSPRef/Reference/reference.html#//apple_ref/doc/c_ref/vDSP_deq22
Arguments:
float *vDSP_A is the input data
float *vDSP_B are 5 filter coefficients
float *vDSP_C is the output data
I have to make 10 filters (10 times vDSP_deq22). Then I set the gain for every band and combine them back together. But what coefficients do I feed every filter? I know vDSP_deq22 is a 2nd order (butterworth) IIR filter, but how do I turn this into a bandpass?
Now I have three questions:
a) Do I have to de-interleave and interleave the audio buffer? I know setting stride to 2 just filters on channel but how I filter the other, stride 1 will process both channels as one.
b) Do I have to transform/process the buffer before it enters the vDSP_deq22 method? If so, do I also have to transform it back to normal?
c) What values of the coefficients should I set to the 10 vDSP_deq22s?
I've been trying for days now but I haven't been able to figure this on out, please help me out!
Your omega value need to be normalised, i.e. expressed as a fraction of Fs - it looks like you left out the f0 when you calculated omega, which will make alpha wrong too:
float omega = 2*M_PI*Fs; // w0 = 2*pi*f0/Fs
should probably be:
float omega = 2*M_PI*f0/Fs; // w0 = 2*pi*f0/Fs
where f0 is the centre frequency in Hz.
For your 10 band equaliser you'll need to pick 10 values of f0, spaced logarithmically, e.g. 25 Hz, 50 Hz, 100 Hz, 200 Hz, 400 Hz, 800 Hz, 1.6 kHz, 3.2 kHz, 6.4 kHz, 12.8 kHz.

Randomize float using arc4random?

I have a float and I am trying to get a random number between 1.5 - 2. I have seen tutorials on the web but all of them are doing the randomization for 0 to a number instead of 1.5 in my case. I know it is possible but I have been scratching my head on how to actually accomplish this. Can anyone help me?
Edit1: I found the following method on the web but I do not want all these decimals places. I only want things like 5.2 or 7.4 etc...
How would I adjust this method to do that?
-(float)randomFloatBetween:(float)num1 andLargerFloat:(float)num2
{
int startVal = num1*10000;
int endVal = num2*10000;
int randomValue = startVal + (arc4random() % (endVal - startVal));
float a = randomValue;
return (a / 10000.0);
}
Edit2: Ok so now my method is like this:
-(float)randomFloatBetween:(float)num1 andLargerFloat:(float)num2
{
float range = num2 - num1;
float val = ((float)arc4random() / ARC4RANDOM_MAX) * range + num1;
return val;
}
Will this produce numbers like 1.624566 etc..? Because I only want say 1.5,1.6,1.7,1.8,1.9, and 2.0.
You can just produce a random float from 0 to 0.5 and add 1.5.
EDIT:
You're on the right track. I would use the maximum random value possible as your divisor in order to get the smallest intervals you can between possible values, rather than this arbitrary division by 10,000 thing you have going on. So, define the maximum value of arc4random() as a macro (I just found this online):
#define ARC4RANDOM_MAX 0x100000000
Then to get a value between 1.5 and 2.0:
float range = num2 - num1;
float val = ((float)arc4random() / ARC4RANDOM_MAX) * range + num1;
return val;
This will also give you double precision if you want it (just replace float with double.)
EDIT AGAIN:
Yes, of course this will give you values with more than one decimal place. If you want only one, just produce a random integer from 15 to 20 and divide by 10. Or you could just hack off the extra places afterward:
float range = num2 - num1;
float val = ((float)arc4random() / ARC4RANDOM_MAX) * range + num1;
int val1 = val * 10;
float val2= (float)val1 / 10.0f;
return val2;
arc4random is a 32-bit generator. It generates Uint32's. The maximum value of arc4random() is UINT_MAX. (Do not use ULONG_MAX!)
The simplest way to do this is:
// Generates a random float between 0 and 1
inline float randFloat()
{
return (float)arc4random() / UINT_MAX ;
}
// Generates a random float between imin and imax
inline float randFloat( float imin, float imax )
{
return imin + (imax-imin)*randFloat() ;
}
// between low and (high-1)
inline float randInt( int low, int high )
{
return low + arc4random() % (high-low) ; // Do not talk to me
// about "modulo bias" unless you're writing a casino generator
// or if the "range" between high and low is around 1 million.
}
This should work for you:
float mon_rand() {
const u_int32_t r = arc4random();
const double Min = 1.5;
if (0 != r) {
const double rUInt32Max = 1.0 / UINT32_MAX;
const double dr = (double)r;
/* 0...1 */
const double nr = dr * rUInt32Max;
/* 0...0.5 */
const double h = nr * 0.5;
const double result = Min + h;
return (float)result;
}
else {
return (float)Min;
}
}
That was the simplest I could think of, when I had the same "problem" and it worked for me:
// For values from 0.0 to 1.0
float n;
n = (float)((arc4random() % 11) * 0.1);
And in your case, from 1.5 to 2.0:
float n;
n = (float)((arc4random() % 6) * 0.1);
n += 15 * 0.1;
For anybody who wants more digits:
If you just want float, instead of arc4random(3) it would be easier if you use rand48(3):
// Seed (only once)
srand48(arc4random()); // or time(NULL) as seed
double x = drand48();
The drand48() and erand48() functions return non-negative, double-precision, floating-point values, uniformly distributed over the interval [0.0 , 1.0].
Taken from this answer.

Divide int's and round up in Objective-C

I have 2 int's. How do I divide one by the other and then round up afterwards?
If your ints are A and B and you want to have ceil(A/B) just calculate (A+B-1)/B.
What about:
float A,B; // this variables have to be floats!
int result = floor(A/B); // rounded down
int result = ceil(A/B); // rounded up
-(NSInteger)divideAndRoundUp:(NSInteger)a with:(NSInteger)b
{
if( a % b != 0 )
{
return a / b + 1;
}
return a / b;
}
As in C, you can cast both to float and then round the result using a rounding function that takes a float as input.
int a = 1;
int b = 2;
float result = (float)a / (float)b;
int rounded = (int)(result+0.5f);
i
If you looking for
2.1 roundup> 3
double row = _datas.count / 3;
double rounded = ceil(_datas.count / 3);
if(row > rounded){
row += 1;
}else{
}