Beginner type conversion - c

I am extremely new to programming in general, so please forgive my noobishness. I am trying to scale down the res[?] array in the function below. I know the problem that the res[?]*(multiplier/100) is creating a decimal answer instead of the required format which is an integer therefore I need to convert the result before it is plugged into the res[?].
I did think of turning res[] array into a double but I wasnt sure whether the initwindow(?,?) was compatible with integer values.
I am on mingw with code blocks. the linker and compiler has customized setting made by my professor. I am on Plain\basic C???
I tried to apply the techniques this website used about the truncating conversion. But doesn't seem to work. http://www.cs.tut.fi/~jkorpela/round.html
Debugger watcher shows that res[?] is equivalent to 0.
#include <stdio.h>
#include <graphics_lib.h>
#include <math.h>
int res[2]//contains a array which contains the vertical and horizontal detected resolution from main()
void function(res)
{
printf("Please note the lowest resolution available is 800x600\n");
printf("Please enter percentage ratio % below 100:");
scanf("%d",&multiplier);
res[1]=(int)(res[1]*(multiplier/100));
res[2]=(int)(res[2]*(multiplier/100));
blah blah blah blah.............
initwindow(res[1],res[2]) //from custom header that my professor made which initializes basic graphics window
return;
}

I'm assuming multiplier is an int to match the %d format.
multiplier/100 is guaranteed to be zero (if the user follows directions and provides a number less than 100). You can do (res[x]*multiplier)/100 to make sure the multiply happens first (you're probably okay without the parentheses, but rather than think about order of operations why not be explicit?)
The cast to int is unnecessary, because an int divided by another int is always an int.
Unless your professor has done some very interesting things, you should also note that a two-element array such as res would have elements res[0] and res[1], not res[1] and res[2].

you don't need to cast in this situation because the conversion is done implicitly . you only need a cast to assign the content of a variable to a variable of different type .

Looks like the multiplier variable is an int, so the result of multiplier/100 expression will be 0 in all cases.
Also, it's a good programming practice to check the validity of user's input.

You must declare multiplier before you use it:
int multiplier;
printf("Please note the lowest resolution available is 800x600\n");
printf("Please enter percentage ratio % below 100:");
scanf("%d",&multiplier);
And the index is staring from 0 not 1. And you should initialize res[0] and res[1] before using them. So:
res[0] = 800;
res[1] = 600;
And the division of multiplier by 100 will truncate to 0, try this without casting as it will be automaticly converted:
res[1]=(multiplier*res[0])/100;
res[1]=(multiplier*res[1])/100;

Related

Setting up Exponential growth function X = a(1+b)^t in C language

I'm writing a program to track the number of rectangles being made in one week using the exponential growth function (X = a(1+b)^t). One person can make 60 rectangles per day.
a represents the initial population, this is the number of people already making rectangles on the first of the week. b represents the growth rate, this is the number of new people making rectangles each day. t represents the time interval, which is 7 days for this program.
I'm having difficulties getting started with the problem, and I need some guidance please.
I was thinking using using math.h and pow, something like this (this code is not compiling)
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
int main() {
int initial_POPULATION;
int time_INTERVAL;
double growth_RATE;
printf("How many people are making rectangles at the
biginning of the week?\n");
scanf("%d", &initial_POPULATION);
printf("How many people are making rectangles each day?
\n");
scanf("%1f", &growth_RATE);
//Exponential growth function X = a(1+b)^t
printf("%d rectangles will be made this week!\n",
initial_POPULATION(pow(1+growth_RATE),time_INTERVAL));
return 0;
}
There are a couple problems, but the most apparent is that you are not setting the value of time_INTERVAL anywhere. Next is the line where the final value is calculated: in C, you need to use * to denote multiplication. Parens do not work as implied multiplication operators like in regular math (at any rate, the way the parenthesis are being used in the last printf is not right). Finally, make sure to read growth_RATE as a double by using %lf as the format specifier in scanf (using %f reads it as a single precision 4-byte value, even though it's declared as a double which is... well, double that).
Try this:
scanf("%lf", &growth_RATE);
time_INTERVAL=7;
printf("%f rectangles will be made this week!\n", initial_POPULATION * pow(1+growth_RATE, time_INTERVAL));
Also, as mentioned by #Asadefa, remove the line breaks from the string literals.
There are 4 possible reasons your code isn't compiling.
Did you try compiling like this if you're using unix, with -lm?
gcc /path/to/file.c -lm -o /path/to/outputfile
Also, you cannot have line breaks in string literals. This isn't allowed:
char *MyString = "Hello
World";
On top of that, you are trying to call initial_POPULATION (int) as if it were a function:
initial_POPULATION(pow(1+growth_RATE),time_INTERVAL)
Maybe you meant:
initial_POPULATION*(pow(1+growth_RATE),time_INTERVAL)
And lastly, time_INTERVAL is uninitialized, as brought up by #Z4-tier.

How to increase the speed of computed Fibonacci caluculations - C

I wrote a small program to compute Fibonacci numbers:
#include <stdio.h>
int main()
{
int first, second, final;
first = 0;
second = 1;
printf("0\n1\n"); /* I know this is a quick fix, but the program still works */
while (final <= 999999999999999999) {
final = first + second;
first = second;
second = final;
printf("%d\n", final);
}
}
Is there any way to increase the speed in which this program computes these calculations? Could you possible explain the solution to me (if it exists)?
Thanks.
Of course it's possible! :)
First of all, please note you're using signed int for your variables, and max int on a 32 bit machine is 2,147,483,647 which is approx. 10^8 times smaller than the max number you're using, which is 999,999,999,999,999,999.
I'll recommend to change the max num to INT_MAX (You'll need to include "limits.h")
Edit:
In addition, as said in the comments to my answer, consider changing to unsigned int. you need only positive values, and the max number will be twice higher.
2nd Edit:
That being said, when final will reach the closest it can to the limit in the condition, the next time its promoted, it'll exceed INT_MAX and will result in an overflow. That means here, that the condition will never be met.
Better to just change the condition to the times you want the loop to run. Please note though, that any fibonacci number larger than the max numder that can be stored in your variable type, will result in an overflow.
Secondly, final isn't initialized. Write final = 0 to avoid errors.
I recommend turning on all the warnings in your compiler. It could catch many errors before they compile :)
Also, I see no reason not to initialize the variables when you declare them. The value is already known.
Now for the speed of the program:
I'm not sure to which extent you're willing to change the code, but the simplest change without changing the original flow, is to make less calls to printf().
Since printf() is a function that will wait for a system resource to become available, this is probably the most time consuming part in your code.
Maybe consider storing the output in a string, and lets say every 100 numbers print the string to the screen.
Try maybe to create a string, with a size of
(10 (num of chars in an int) + 1 (new line char) )* 100 (arbitrary, based on when you'll want to flush the data to the screen)
Consider using sprintf() to write to a string in the inner loop, and strcat() to append a string to another string.
Then, every 100 times, use printf() to write to the screen.
As already stated in other answers, you have obvious two problems. 1) The missing initialization of final and 2) that your loop condition will result in an endless loop due to 999999999999999999 being larger than any integer value.
The real problem here is that you use a fixed number in the condition for the while.
How do you know which number to use so that you actually calculates all the Fibonacci numbers possible for the used integer type? Without knowing the numbers in advance you can't do that! So you need a better condition for stopping the loop.
One way of solving this to check for overflow instead - like:
while (second <= (INT_MAX - first)) { // Stop when next number will overflow
The above approach prevents signed overflow by checking whether the next first + second will overflow before actually doing the first+second. In this way signed overflow (and thereby UB) is prevented.
Another approach is to use unsigned integers and deliberately make an overflow (which is valid for unsigned int). Using unsigned long long that could look like:
unsigned long long first, second, next;
first = 1;
second = 1;
printf("1\n1\n");
next = first + second;
while (next > second) { // Stop when there was an overflow
printf("%llu\n", next);
first = second;
second = next;
next = first + second;
}
Speed isn't your problem. You have an infinite loop:
while (final <= 999999999999999999) {
final has type int. Most likely int is 32-bit on your system, which means the maximum value it can hold is 2147483647. This will always be smaller than 999999999999999999 (which is a constant of type long long), so the loop never ends.
Change the datatype of your variables to long long and the loop will terminate after about 87 iterations. Also, you'll need to change your printf format specifier from %d to %lld to match the datatype printed.
Why are you asking this question?
If it's the intention to increase the performance, you might go for the formula of the n-th Fibonacci number, which is something like:
((1+v5)/2)^n + ((1-v5)/2)^n, something like that (v5 being the square root of 5).
If it's about learning to increase performance, you might do a code review or use performance diagnostics tools.

C -- Double type data: Number slightly larger than allowed is able to slip through the conditions

I'm new to C language, it is required for my degree to complete one course on C programming. Hope the title makes sense... I had a hard time trying to convey what I meant. I'll elaborate here.
The problem I am facing right now is double type data being able to slip through the program undetected when it should have been rejected. This happens when a number very very close to the boundaries I set is provided.
In this assignment, in order to get an HD, my code has to have identical output to the lecturer's. The solutions are able to detect any number larger than the boundaries, no matter how close.
Basically, the program will ask the user to provide a GPA which is from 0 to 4.
I tried the following inputs:
4.01 rejected
4.001 rejected
...
4.000001 rejected
But at 4.0000001, it is accepted. This should not happen at all. I am baffled.
Here's my code:
double GPA=-1; /*Flags are being initialised*/
int GPAflag=1;
while(GPAflag){
char str[50];
char *ptr;
int isnum=1,n=0,i,point=0;
printf("Enter GPA>");
fflush(stdin);
gets(str);
n = strlen(str);
if(n==0){ /*string length is 0? There was no input, thus invalid*/
printf("Invalid GPA. ");
isnum=0;
}else{
for(i=0;i<n;i++) /*Validates numerical inputs, if not numerical, prompts user with error*/
if(!(str[i]>='0' && str[i]<='9')){
if(str[i]!='.'){
printf("Invalid GPA. ");
isnum=0;
break;
}else{
point++;
}
}
}
if(isnum){ /*If the input is a number, it may still be invalid*/
GPA=strtod(str, &ptr); /*The string is converted to a double*/
if(GPA>=0&&GPA<=4&&point<=1) /*If GPA is between 0 and 4, and the above is also satisfied (point=1), then the flag is 0 and thus a valid input*/
GPAflag=0;
else
printf("Invalid GPA. "); /*If not, it is still invalid*/
}
}
I personally don't think this will be a problem but I would really like to know why it happens, and if possible, a way to fix it.
I can simply make a FOR loop:
IF leading number is 4 and there's a '.'
-> Reject
But this seems like hard coding to me, I think it's rather a workaround than an actual solution.
Or I can change the IF statement from "<=4" to "<4.0000000000000000000000...1". Which in my opinion should lose marks... (if I was the marker I will take marks off for that)
Also, I am totally aware that the function "gets" is primitive and causes many problems (overflow... etc.). I have tried using fgets but it's a pain to implement... replacing the '\n' with '\0' blah blah... we haven't even learnt gets, let alone fgets. Is there a better way to implement fgets? Maybe have a function to replace the '\n'? I've tried that and it refused to work.
Any help and tips are greatly appreciated!
OP's true code was using float GPA=-1; and so GPA=strtod("4.0000001", &ptr); resulted in a GPA value of exactly 4.0 due to the greater limited precision of float versus a double.
By using double GPA;, as in the posted code, GPA=strtod("4.0000001", ... and GPA=strtod("4.000000001", ... will return a value just greater than 4. Even GPA=strtod("4.00000000000001", ... is likely to return a value a bit larger than 4.
At some point the limited precision of double will render GPA=strtod("4.0 many digits 001", ... as 4.0. A typical solution to limit the number of digits to something like 15 or less.
(Could taunt the user if more that 15 digits are used.)
The problem is solved, and looking back, it was due to a mistake:
In the structure, I have declared GPA as a float. I later changed it in my functions but missed out the most important part. As a result, the GPA was still stored as a float. Hope this conclusion is correct.
The limitations of the datatype causes round-off errors when an incredibly "close to allowed" value is provided.
Lesson learnt: When changing something, always make sure everything is consistent.
I appreciate all the help! Thanks a lot!

Why does this print only 0?

New to C, I've been trying to convert a hex input with this code. The input argv[1] I've been giving it is 0xabcd123. It has only given me 0 outputs. I have also tried using atoi as well as varying the types of outputs. Why does it only print 0? Here is the code, thanks
#include <stdio.h>
#include <stdlib.h>
typedef union{
double num;
float f;
} U;
int main(int argc, char*argv[])
{
U u;
u.num = strtod(argv[1], NULL);
printf("%e\n", u.f);
return 0;
}
result is platform dependent!
I believe its returning 0 on one system because of byte order. when you write to the value as a double but then read it as a float, you may be reading the top or bottom half of the double, depending on the architecture. on one system it's the empty top half of the double, on another its the bottom half which contains value.
either way, with a union, you should never expect to write any value as one type, and read back as another and get reliable results. as you have discovered :) unions aren't magic type converters, they simply allow you to save space when you know you have one type of value at a time.
num is declared as int. So printf("%d", u.num) or double num
First, please kindly reformat your code so that everyone can read it easily.
Second, the type of your u.num is double, so utilize %f or %lf instead of %d
Third, as shown in this codepad http://codepad.org/JSSJEKOn, your code is correct and it must obviously print the expected result. So I think that the error is not here but somewhere else in your source file. Please give us more information

codechef :wrong answer error in smallfactorial

#include<stdio.h>
int fact(int k)
{
int j,f=1;
for(j=1;j<=k;j++)
f*=j;
return f;
}
int main()
{
int t,i,n[100],s[100],j;
scanf("%d",&t);
for(i=0;i<t;i++)
{
scanf("%d",&n[i]);
}
for(j=0;j<t;j++)
{
s[j]=fact(n[j]);
printf("%d \n",s[j]);
}
return 0;
}
You are asked to calculate factorials of some small positive integers.
Input
An integer t, 1<=t<=100, denoting the number of testcases, followed by t lines, each containing a single integer n, 1<=n<=100.
Output
For each integer n given at input, display a line with the value of n!
Example
Sample input:
4
1
2
5
3
Sample output:
1
2
120
6
Your code will give correct results for the given test cases but that doesn't prove that your code works. It is wrong is because of integer overflow. Try to calculate 100! by your program and you'll see what's the problem.
My answer lacked details. I'll update this to add details for an answer to the question as it stands now.
C has limitations over the the maximum and minimum size that can be stored in a variable. For doing arbitrary precision arithmetic it is usually advisable to use a bignum library as PHIFounder has suggested.
In the present case however, the use of external libraries is not possible. In this case arrays can be used to store integers exceeding the maximum value of the integers possible. OP has already found this possibility and used it. Her implementation, however, can use many optimizations.
Initially the use of large arrays like that can be reduced. Instead of using an array of 100 variables a single variable can be used to store the test cases. The use of large array and reading in test cases can give optimization only if you are using buffers to read in from stdin otherwise it won't be any better than calling scanf for reading the test cases by adding a scanf in the for loop for going over individual test cases.
It's your choice to either use buffering to get speed improvement or making a single integer instead of an array of 100 integers. In both the cases there will be improvements over the current solution linked to, on codechef, by the OP. For buffering you can refer to this question. If you see the timing results on codechef the result of buffering might not be visible because the number of operations in the rest of the logic is high.
Now second thing about the use of array[200]. The blog tutorial on codechef uses an array of 200 elements for demonstrating the logic. It is a naive approach as the tutorial itself points out. Storing a single digit at each array location is a huge waste of memory. That approach also leads to much more operations leading to a slower solution. An integer can at least store 5 digits (-32768 to 32767) and can generally store more. You can store the intermediate results in a long long int used as your temp and use all 5 digits. That simplification itself would lead to the use of only arr[40] instead of arr[200]. The code would need some additional changes to take care of forward carry and would become a little more complex but both speed and memory improvements would be visible.
You can refer to this for seeing my solutions or you can see this specific solution. I was able to take the use down to 26 elements only and it might be possible to take it further down.
I'll suggest you to put up your code on codereview for getting your code reviewed. There are many more issues that would be best reviewed there.
Here, your array index should start with 0 not 1 , I mean j and ishould be initialized to 0 in for loop.
Besides, try to use a debugger , that will assist you in finding bugs.
And if my guess is right you use turbo C, if yes then my recommendation is that you start using MinGW or Cygwin and try to compile on CLI, anyway just a recommendation.
There may be one more problem may be which is why codechef is not accepting your code you have defined function to accept the integer and then you are passing the array , may be this code will work for you:
#include<stdio.h>
int fact(int a[],int n)// here in function prototype I have defined it to take array as argument where n is array size.
{
int j=0,f=1,k;
for (k=a[j];k>0;k--)
f*=k;
return f;
}
int main()
{
int t,i,n[100],s[100],j;
setbuf(stdout,NULL);
printf("enter the test cases\n");
scanf("%d",&t); //given t test cases
for(i=0;i<t;i++)
{
scanf("%d",&n[i]); //value of the test cases whose factorial is to be calculated
}
for(j=0;j<t;j++)
{
s[j]=fact(&n[j],t);// and here I have passed it as required
printf("\n %d",s[j]); //output
}
return 0;
}
NOTE:- After the last edit by OP this implementation has some limitations , it can't calculate factorials for larger numbers say for 100 , again the edit has taken the question on a different track and this answer is fit only for small factorials
above program works only for small numbers that means upto 7!,after that that code not gives the correct results because 8! value is 40320
In c language SIGNED INTEGER range is -32768 to +32767
but the >8 factorial values is beyond that value so integer cant store those values
so above code can not give the right results
for getting correct values we declare the s[100] as LONG INT,But it is also work
only for some range

Resources