Having trouble creating a weather converter program - objective-c

I started school for computer programming just a couple weeks ago and we just started Objective-C! We need to convert Celsius to Fahrenheit and Kelvin. To do that I must input the amount of Celsius. Then I use this equation to get Fahrenheit: * 9 / 5 + 32. To get Kelvin I add 273.15.
#include <stdio.h>
int main(void)
{
float Celsius;
float Farenheight = Celsius * 9 / 5 + 32;
float Kelvin = Celsius + 273.15;
printf("How many degrees in Celsius?");
scanf("%s %s %d", Celsius, Farenheight, Kelvin);
printf("C: %s, F: %s, K: %d", Celsius, Farenheight, Kelvin);
}
This is (the second revision of) what I came up with so far, but I am really unsure on how to do this. If anyone can help me that would be great!

Funnily enough, temperature conversion came up in another context earlier today.
Adapting that code to your outline, you need to read the value in celsius before you convert anything to kelvin or fahrenheit (whereas your code converts an uninitialized value, which is not a good idea):
double celsius;
printf("What is the temperature in degrees Celsius? ");
if (scanf("%lf", &celsius) == 1)
{
double kelvin = celsius + 273.15;
double fahrenheit = (celsius + 40.0) * (9.0 / 5.0) - 40.0;
printf("%7.2f °C = %7.2f K = %7.2f °F\n", celsius, kelvin, fahrenheit);
}
Note that the input is checked for validity before the result is used.
The conversion formula is simpler than the usual one you see quoted, and is symmetric for converting °F to °C or vice versa, the difference being the conversion factor (9.0 / 5.0) vs (5.0 / 9.0). It relies on -40°C = -40°F. Try it:
C =  0°C; (C+40) = 40; (C+40)*9 = 360; (C+40)*9/5 = 72; (C+40)*9/5-40 = 32°F.
F = 32°F; (F+40) = 72; (F+40)*5 = 360; (F+40)*5/9 = 40; (F+40)*5/9-40 =  0°C.
Absolute zero is -273.15°C, 0K, -459.67°F.

Use this code snippet to read input from stdin:
#include <stdio.h>
int main (int argc, char *argv[]) {
int celsius;
printf("What is the temperature in celsius? ");
scanf("%d", &celsius);
printf("celsius degree = %d\n", celsius);
}

Related

Linear equation of two vaariable

I want to find the solutions of linear equation of two variable(i know that there are infinitly many solution but i have to print some of them!)
so i tried in C language
what i have did is simply taken the input of coefficient of X,Y and c. Then calucalted the values as you can see it in the code Then calculated that if the result is satisfying the equation(means it is =0 or not) then checked and print. After that i have incremented the value of x,y so that it can be calculaed with different numbers(in the first i have put it by default 0)..
here is the code please see the code and tell me what is problem and am i doing mistake to choose the type of variable etc..
if possible please give me the correct code(request).
code in C:-
#include <stdio.h>
int main()
{
float a, b, c, Rx, Ry;
int sol;
float x, y;
printf("The Linear equation in two variable\n");
printf("Formate is aX+bY+c=0\n");
printf("Enter the coefficient of 'X'\n");
scanf("%f", &a);
printf("Enter the coefficient of 'Y'\n");
scanf("%f", &b);
printf("Enter the coefficient of constant 'c'\n");
scanf("%f", &c);
printf("Your equation looks like\n");
printf("%0.0fX+%0.0fY+%0.0f=0\n", a, b, c);
x = 0;
y = 0;
for (int i = 0; i < 10; i++)
{
// for x
x = ((-c) + (-b * y)) / b;
printf("The value of x is %0.2f\n", x);
// for y
y = ((-c) + (-a * x)) / a;
printf("The value of y is %0.2f\n", y);
// checking wheter the value of x and y satisfy the equation (which is equal to 0)
sol = (a * x) + (b * y) + (c);
printf("The value of sol is %0.2f\n", sol);
x++;
y++;
if (sol == 0)
{
printf("The value of x at %d time is %0.2f\n", i, x);
printf("The value of y at %d time is %0.2f\n", i, y);
}
else
continue;
}
return 0;
}
am i doing mistake to choose the type of variable
int sol;
…
printf("The value of sol is %0.2f\n", sol);
Whether the choice of type int for sol is a mistake depends on which precision you want. In any case, the conversion specifier f and type int don't fit together; you have to bring those in line. Be aware that if you choose float for sol, the comparison sol == 0 will not very likely succeed.

Rounding a float number in objective-c

I want to know if there is a simple function that I can use such this sample.
I have a
float value = 1.12345;
I want to round it with calling something like
float value2 = [roundFloat value:value decimal:3];
NSLog(#"value2 = %f", value2);
And I get "1.123"
Is there any Library or default function for that or I should write a code block for this type of calculations?
thank for your help in advance
Using NSLog(#"%f", theFloat) always outputs six decimals, for example:
float theFloat = 1;
NSLog(#"%f",theFloat);
Output:
1.000000
In other words, you will never get 1.123 by using NSLog(#"%f", theFloat).
Cut-off after three decimals:
float theFloat = 1.23456;
float newFLoat = (int)(theFloat * 1000.0) / 1000.0;
NSLog(#"%f",newFLoat);
Output:
1.234000
Round to three decimals (using roundf() / lroundf() / ceil() / floor()):
float theFloat = 1.23456;
float newFLoat = (int)(roundf(theFloat * 1000.0)) / 1000.0;
NSLog(#"%f",newFLoat);
Output:
1.235000
Round to three decimals (dirty way):
float theFloat = 1.23456;
NSString *theString = [NSString stringWithFormat:#"%.3f", theFloat];
float newFloat = [theString floatValue];
NSLog(#"%#",theString);
NSLog(#"%f",newFloat);
Output:
1.235
1.235000
For printing the value use:
NSLog(#"value2 = %.3f", value2);
Rounding to 3 decimal digits before calculations doesn't really make sense because float is not a precise number. Even if you round it to 1.123, it will be something like 1.122999999998.
Rules:
Usually you round up only to print the result - string formatter can handle it (see above).
For precise calculations (e.g. currency), don't use floating point, use NSDecimalNumber or fixed point arithmetics.
Floating point numbers don't have decimal places, they have binary places. Decimal-radix numbers have decimal places. You can't round floating point numbers to specific numbers of decimal places unless you convert to a decimal radix. No routine, method, function etc., that returns a floating point value can possibly carry out this task.
Note that "Round" is not necessarily as simple a topic as you think. For example
DIY Calculator: Rounding Algorithms 101 lists 16 different methods for rounding a number.
Wikipedia:Rounding covers a lot of the same ground
And Cplusplus has source code for a bunch of Rounding Algorithms that are easy translatable to objective-c
How you want to round will depend on the context of what you are doing with for data.
And I should point out that Stack Overflow already has a plethora of other questions about rounding in objective-c
//Your Number to Round (can be predefined or whatever you need it to be)
float numberToRound = 1.12345;
float min = ([ [[NSString alloc]initWithFormat:#"%.0f",numberToRound] floatValue]);
float max = min + 1;
float maxdif = max - numberToRound;
if (maxdif > .5) {
numberToRound = min;
}else{
numberToRound = max;
}
//numberToRound will now equal it's closest whole number (in this case, it's 1)
Here is a simple way to do it:
float numberToRound = 1.12345f;
float remainder = numberToRound*1000.0f - (float)((int)(numberToRound*1000.0f));
if (remainder >= 0.5f) {
numberToRound = (float)((int)(numberToRound*1000.0f) + 1)/1000.0f;
}
else {
numberToRound = (float)((int)(numberToRound*1000.0f))/1000.0f;
}
For an arbitrary decimal place, substitute 1000.0f in the above code with
float mult = powf(10.0f, decimal);
try
#import <math.h>
float cutFloat( float number, int decimal) {
number = number*( pow(10,decimal) );
number = (int)number;
number = number/( pow(10,decimal) ) ;
return number;
}

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.

Working out Oscillator wave type code, and creating new wave types

I want to work out a bit of code that generates the oscillator wave-type in my tone generator app. The one in this example is a sine-wave, can someone tell me how the code works, as i want to in the future make custom wave-types and square, sawtooth and triangle types.
OSStatus RenderTone(
void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData)
{
// Fixed amplitude is good enough for our purposes
const double amplitude = 0.25;
// Get the tone parameters out of the view controller
ToneGeneratorViewController *viewController =
(ToneGeneratorViewController *)inRefCon;
double theta = viewController->theta;
double theta_increment = 2.0 * M_PI * viewController->frequency / viewController->sampleRate;
// This is a mono tone generator so we only need the first buffer
const int channel = 0;
Float32 *buffer = (Float32 *)ioData->mBuffers[channel].mData;
// Generate the samples
for (UInt32 frame = 0; frame < inNumberFrames; frame++)
{
buffer[frame] = sin(theta) * amplitude;
theta += theta_increment;
if (theta > 2.0 * M_PI)
{
theta -= 2.0 * M_PI;
}
}
// Store the theta back in the view controller
viewController->theta = theta;
return noErr;
}
The actual sine wave samples are being generated and are populating the buffer in the snippet below
for (UInt32 frame = 0; frame < inNumberFrames; frame++)
{
buffer[frame] = sin(theta) * amplitude;
theta += theta_increment;
if (theta > 2.0 * M_PI)
{
theta -= 2.0 * M_PI;
}
}
In the line where buffer[frame] is being assigned, you are calling sin(theta) * amplitude, and for each iteration of the for loop, you are incrementing theta by some finite step size based on your frequency and sample rate, via
double theta_increment = 2.0 * M_PI * viewController->frequency / viewController->sampleRate;
Which is essentially dividing 2.0 * PI * frequency by your sample rate.
Incrementing the theta variable while looping through the for loop is basically advancing the time step one sample at a time until your buffer is full (i.e. frame == iNumberFrames).
If you wanted to generate something other than a sine wave, you would simply replace the following line with some other function:
buffer[frame] = sin(theta) * amplitude;
I.e. let's say, for example, you wanted the first three terms in the infinite Fourier series that converges to a triangle wave; you might then have the following instead...
buffer[frame] = (8 / pow(M_PI,2)) * (sin(theta) - sin(3*theta)/9 + sin(5*theta)/25);
To produce your desired waveform, you need to replace the sin() function with a function that produces your desired wave shape.
You might be able to find this function in a table of functions with graphical examples, or you might have to create your function. The are lots of ways to create a functional approximation, including polynomial, Fourier series, table lookup with or without interpolation, recursions, and etc. But that is a big subject on its own (many textbooks, etc.)

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.