Here's the body of my code
int OP, NP, first, second, third, blankets, remainder;
printf("How many people are knitting blanket squares at the beginning of the week?\n");
scanf("%d", &OP);
printf("How many new people are knitting blanket squares each day?\n");
scanf("%d", &NP);
//formula
first = 1 + NP;
second = pow(first,7);
third = OP * second;
blankets = third / (double)60;
remainder = third - blankets * 60;
printf("%d blanket squares will be made this week!\n", third);
printf("You will be able to make %d blankets and start next week with %d squares.", blankets, remainder);
This is sufficient except for when I enter a decimal (such as .5) in the place of NP. When I do that, I get an overflow and it outputs the value -2147483648 for the first printf. Is all I have to do change the data type? Sorry for a very simple question, I'm very new.
Doing floating point arithmetics with integers, could overflow the integers. That is possible, but unlikely. You also loose precision of course. You need to use at least float for this calculations.
The real problem:
Using scanf() incorrectly.
Passing a floating point value to scanf() where it expects an integer. It fails but you don't know, because of (1).
Using scanf() like that leads to undefined behavior, your variables NP and OP were never initialized. But you don't know that, because you didn't check the return value of scanf().
You MUST check it, like this
if (scanf("%d", &NP) != 1) {
fprintf(stderr, "Error, bad input, expecting an `int'.\n");
// Now, `NP' is not initialized unless it was before calling
// `scanf' so you can't continue using `NP' safely from
// this point
}
The same goes for OP.
If you want floating point values (and you do, because you say so in your question) use
float NP, OP;
if (scanf("%f", &NP) == 1) ...
Related
I was making a little program to test floats in the C: The program itself is very simple, I just want to based on the User's input, return how much Dollar(s), Quarter(s)... etc, his number has.
//------------------------------> First Part: All the necessary Variables <-----------------------------
int main (void)
{
//Getting the user Input
float number = get_float("Number: ");
//Checking if is a positive number
if (number < 0)
{
printf("A positive number, Please: ");
}
//Declaring my Constant/Temporary variables.
float coinValues[] = {1.00, 0.25, 0.10, 0.5, 0.01};
char *coinNames[] = {"Dollar(s): ", "Quarter(s): ", "Dime(s): ", "Nickel(s): ", "Penny(ies): "};
int i = 0;
int tmp = 0;
//-----------------------------------> Second Part: The code Itself <-----------------------------------
//Checking/Printing the necessary coins.
while (number > 0)
{
//Until the loop stops, check if the number can be divided by the CoinValue.
if (number >= coinValues[i])
{
//Print the current Coin Name from the divided value.
printf("%s", coinNames[i]);
//Check if the Current Number still contains Coin Values inside of it, if True counts one in your "Coin Score".
while (number >= coinValues[i])
{
number -= coinValues[i];
tmp++;
}
//Print the Current "Coin Score", then resets TMP.
printf("%i\n", tmp);
tmp = 0;
}
else
{
//Updating the Coin value
i++;
}
}
}
My program was running very well as long I use Integers, but when I converted this code for Floats the values (Dime(s), Nickel(s), and Penny(ies)) start to return non-expected results in the Int variable tmp.
An expected result for a number like 2.6, will be 2 Dollars, 2 Quarters, and 1 Dime, but sometimes, instead of use the Dime(s), the program skips them entire and make the operation with the Nickel(s), however, what is bugging me is that the program is always returning AWL=+ without any value and then the program stay froze forever.
Considering that my only thought is that I'm "suffering" from Float Imprecision, and I don't know how to solve it, so can anyone Help me?
Ps. The program needs to always return the maximum value from each coin before pass forward.
Floating-point arithmetic is designed to approximate real-number arithmetic. IEEE 754-2008 says “Floating-point arithmetic is a systematic approximation of real arithmetic…” So there is no way to “lock” decimal digits in binary floating-point. It is intended to be used where you want an approximation, such as modeling physics. That even includes some financial applications, such as options evaluation. Although floating-point arithmetic can be used for exact calculations in some situations, these require particular care and are generally only pursued in special circumstances.
So the answer to your question on how to lock decimal places is there is no good way to do that with binary floating-point. Attempting to do so generally just yields the same effects as integer arithmetic but less efficiently and with more difficult code. So use integer arithmetic and scale the amounts according to the smallest unit of currency desired, such as a penny.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
So I am new to C, and I mainly use it to make calculators for probability and stuff like that. My current project finds the increase and decrease of 2 values.
The code is:
#include <stdio.h>
//Variables
//Main Area
int
main ()
{
float num1;
float num2;
float num3;
float num4;
float answer;
//Scanning for the first number
printf ("\n Please Enter the first Value : ");
scanf ("%f", &num1);
//scanning for the second number
printf ("\n Please Enter the second Value : ");
scanf ("%f", &num2);
//calculating
num3 = num1 - num2;
num4 = num3 / num1;
answer = num4 * 100;
//Checking if the answer is an increase or decrease
if (answer > 0) {
printf("The answer has been decreasedby: %f\n", answer);
printf("percent");
}
else {
printf("The answer has been increased by: %f\n", answer * -1);
printf("percent");
}
//Printing the answer
}
The output:
Please Enter the first Value: 9
Please Enter the second Value : 90
The answer has been increased and the final value is: 900.000000
percent
So I set all the values as Floats rather than Ints because Ints only support whole numbers. But when I do get a whole number rather then displaying only the single number with no decimal points, it produces a number with the number and a bunch of zeros after the decimal point. Is there a way to detect if the number Is a whole number and just display that number?
Thanks
Is there a way I can detect if the answer is a whole number and only display that number?
To detect if float is a whole number, use modff() to break a float into its whole number and fractional parts.
float f;
float ipart;
float fpart = modff(f, &ipart);
printf("%g is %s whole number.\n", f, fpart == 0.0 ? "a" : "not a");
An alternative to detecting "whole-ness", use "%g" to print floating point numbers with reduced output.
printf("%g\n", 2.0/3.0); // 0.666667
printf("%g\n", 1234.0); // 1234
Perhaps a step further with "%g". Use a precision wide enough to show any non-zero digits to the right of the . and let the specifier lop off the trailing zeros when the answer is a whole number.
printf("%.*g\n", FLT_DECIMAL_DIG, some_float);
printf("%.*g\n", DBL_DECIMAL_DIG, some_double);
Compare answer to the return value of f.e. the floorf() function (header math.h) - floorf() since you dealing with a variable of type float - with answer passed as argument.
By doing so, you proof if answer contains an even decimal value.
For the output itself, Use a precision specifier (f.e. .0) which specifies the amount of digits in the fraction part and place it between the % and the f conversion specifier, For example %.0f.
The precision of .0 specifies that you want to display no fraction part.
// Checking if the answer is an increase or decrease
if ( answer > 0 ) {
if ( answer == floorf(answer) ) // If answer contains a decimal value.
printf("The answer has been decreased and the final value is: %.0f\n", answer);
else
printf("The answer has been decreased and the final value is: %.3f\n", answer);
}
else {
if ( answer == floorf(answer) ) // If answer contains a decimal value.
printf("The answer has been increased and the final value is: %.0f\n", answer * -1);
else
printf("The answer has been increased and the final value is: %.3f\n", answer * -1);
}
Side Notes:
Note that floating-point often does not provide expected results:
Is floating point math broken?
So, it is possible that even this technique will not work at each and every use case.
Always check the return value of input functions such as scanf() if an input error occurred.
I used floorf(), but ceilf(), truncf() or roundf() could also be used to achieve the same effect.
int main() is deprecated. Use int main(void) instead which declares a full prototype for main().
Since answer will be negative when reaching the else body, printing answer * -1 will output a positive value, since - * - = +. Maybe this is not intended, so this just as a hint.
My way of checking involves :
if(num1 == (int)num1) // This checks whether num1 is integer
{
//Do something
}
else
{
//num1 is float
}
I'm trying to write a code that asks from the user to give 5 coefficients for a 5th-degree polynomial, and it also asks to give a range (two values) that the programs checks if there is a solution in it or not (I'm asked to find only one), and the solution must be an integer, while the coefficients can be floats.
I'm thinking of writing a code that runs over every integer in the range and substitute it in a description of a polynomial than I define, and check if its equal to zero, but I got stuck at deciding how to make the loops.
And another thing, if there are more than one root in the interval that the user enters, then we must print the minimal value of the roots (but I have no direction how to do that either).
I will show you what I wrote so far, and any kind of help would be appreciated:
#include <stdio.h>
#define zero 0.00001
int main()
{
double a, b, c , d , e , f , y , beginning_of_range, end_of_range;
int x;
printf("please enter the coefficients of the polynomial:\n");
scanf("%lf%lf%lf%lf%lf", &a, &b, &c, &d, &e);
printf("please enter two values to indicate the beginning and end of range:\n");
scanf("%lf%lf", &beginning_of_range, &end_of_range);
while (beginning_of_range > end_of_range)
{
printf("ERROR: the range you have entered isn't valid, please try again:");
scanf("%lf%lf", &beginning_of_range, &end_of_range);
}
while (beginning_of_range < end_of_range)
{
x = beginning_of_range;
y = a + b*x + c*x*x + d*x*x*x + e*x*x*x*x + f*x*x*x*x*x;
if (y == zero)
{
printf("the root is:%d", x);
}
else
{
x = x+1;
}
break;
}
return 0;
}
Your task as written is very questionable, so much so that there is perhaps a mis-interpretation or mis-communication.
A randomly given polynomial with floating point coefficients will have integer roots with probability so close to zero that it is practically impossible.
Even with integer coefficients it requires carefully reverse-engineered coefficients to get an integer root. Just change one coefficient by one and in most cases all roots will be irrational.
What you can do in your framework is to find intervals with a sign change so that there is at least one root inside the interval that can be found using one of bisection, regula falsi, Illinois, secant or Mullers methods. All of them derivative free.
Without identifying all roots, also the complex ones, it is rather hard to guarantee that all real roots have been found. Thus it is only approximately possible to find the smallest real root inside the given interval. There might be an integer interval with two real roots inside so that at the boundaries the sign is the same. You would have to analyse the signs of all derivatives at the integer points to make more reliable guesses in this case, see Descartes rule and Budan-Fourier theorem.
Your first while loop should probably be an if statement instead of a loop.
Your second (main) while loop never increments the beginning of range. This is probably causing an endless loop for you.
I'm quite a beginner in this topic, and couldn't find out the reason: sometimes the program works, sometimes not (after asking the question, it simply doensn't want to take in my answers, than I can write in as much as I want, it doesn't respond, just list out the numbers, I tiped in)
#include <stdio.h>
float abszolut (float szam)
{
float abszoluterteke;
if (szam >=0)
abszoluterteke = szam;
else
abszoluterteke = -szam;
return abszoluterteke;
}
float negyzetgyok (float szam)
{
float pontossag = 0.000001;
float tipp = 1;
if (szam <0)
{
printf ("Megszakítás elfogadva! \nKöszönjük, hogy programunkat választotta!\n");
return -1;
}
else
{while (abszolut (tipp*tipp-szam) >= pontossag)
tipp = (szam/tipp + tipp)/2;
return tipp;
}
}
int main (void)
{
float alap, eredmeny;
for (;;)
{
printf ("Melyik számnak szeretnéd meghatározni a négyzetgyökét ilyen módszerrel?\n");
scanf ("%f", &alap);
eredmeny = negyzetgyok (alap);
if (eredmeny == -1)
return 1;
else
printf ("A(z) %f négyzetgyöke megfelelő közelítéssel: %f\n", alap, eredmeny);
}
return 0;
}
Change for abszolut (tipp*tipp-szam) >= pontossag*szam
The while loop must stop once tipp*tipp is close to szam. But IEEE floating point computations have a limited precision : about 7 digits for float and 15 digits for double.
So the error on float szam is about 0.0000001*szam. It's the same for tipp. Consequently, the error on tipp*tipp-szam is higher than 0.0000001*szam. If szam is large, this error will hardly become lower than 0.000001. Even if double precision is used, it is likely that while (abszolut (tipp*tipp-szam) >= pontossag) triggers an infinite loop for very large numbers.
On the other side, what happens if szam is very small, say 1e-10 ? The while loop prematurely exits and the square root of 1e-10 is computed as something about 1e-3, instead of 1e-5... The relative error is about 10000%... And using double does not change anything !
To avoid this, you can change for abszolut (tipp*tipp-szam) >= pontossag*szam.
Notice that both sides have the same dimension. If szam were in square feet, tipp would be in feet and pontossag, the precision, is dimensionless. It is a good practice to compare things having the same dimension.
If you keep noticing infinite loops, switch to double precision or increase pontossag.
To avoid infinite loop, add a counter int i; and exit the while loop if the number of iteration is 100. 100 should be sufficient, since your Newton-Raphson iteration features a quadratic convergence.
There are a number of problems with your code.
The exit condition in your loop is flawed.
The problem with your square root algorithm is the use of the error limit pontossag. Your algorithm will give erroneous results for very small numbers and it will loop forever for numbers larger than 20 or so. To fix this, change the loop test from abszolut (tipp*tipp-szam) >= pontossag to abszolut (tipp*tipp-szam) >= pontossag*szam.
You aren't checking for all the problem cases.
If your computer uses IEEE 754 floating point, your algorithm happens to work. That's just luck. Never rely on luck when doing numerical programming. It's easy to input an infinity. For example, 3.5e38 (350000000000000000000000000000000000000) does the trick with single precision numbers (float). Your function negyzetgyok should check for infinity:
if (isinf (szam))
{
return szam;
}
You can do much better than an initial guess of 1.0 as the square root.
An initial guess of 1.0 against 3.4e38 means a lot of needless looping. A fast and easy way to form a good initial guess is to take advantage of the fact that floating point numbers are represented internally as (1+fractional_part)*2^exponent. A good first guess is 1*2^(exponent/2). With single precision numbers,
int expo;
float tipp;
frexpf (szam, &expo);
tipp = ldexpf (1.0f, n/2);
You are using %f rather than %g to parse floating point numbers.
The %g format can parse anything that can be parsed with the %f format, plus a whole lot more.
You aren't checking the status of fscanf.
Enter x when prompted to enter a number. The scanner will read that character, which stops the scan. The scanner will put that character (x) back into the input buffer, and return 0, indicating that nothing was scanned. The next time around, the scanner will read the character x again, once again put that character back into the input buffer, and once again return 0. Infinite loop! Always check the status of any of the scanf family of functions to see if the scanner scanned the number of items expected.
You are using fscanf.
There are a number of existing questions and answers at this site that address the many problems with using fscanf to read from a file. This is particularly so when reading human-generated input. People make mistakes. Ignoring that people do make mistakes on entering data is a programming error. A better approach would be to read a line into a buffer using frets and parse that line with sscanf.
I am writing a function that ask the user for input and then checks if that input is infact a positive number if not it loops until a positive number is inputed and then returns that values. This is what i have so far but when it returns im getting a weird number like 20204421.000 any help?
/* Checks if rate is infact positive and loops until a positive number is inputed */
int checkposrate(int rentrate)
{
while (rentrate < 0){
printf("Please enter the anual rental rate per square foot(must be positive number):");
scanf("%f",&rentrate);
}
return rentrate;
}
You should use scanf("%d", &rentrate); to get an integer value. "%f" is used when you want to input a floating point number.
If you want more information about how scanf() works, you can take a look in here.
Slightly off-topic, but I don't like the declaration: you aren't using rentrate as an input at all, so that shouldn't be a parameter.
int checkposrate() {
int rentrate;
Second, as others have said, you need %d instead, but I would actually use %u - this only accepts positive integers. If you set rentrate to start as equal to 0, then it is only set by scanf when the user enters a valid unsigned integer, leaving you with this code. Note that this assumes that zero is not a valid positive number:
/* Checks if rate is in fact positive and loops until a positive number is read from input */
unsigned int checkposrate()
{
unsigned int rent_rate = 0;
while (rent_rate <= 0){
printf("Please enter the annual rental rate per square foot (must be a positive integer): ");
scanf("%u",&rent_rate);
}
return rent_rate;
}
If, on the other hand, you do want fractional rental rates, you were right with %f, but had the wrong variable types in your code:
double checkposrate() {
double rent_rate = -1.0;
while (rent_rate < 0.0 && rent_rate) {
printf("Please enter the rental rate per sq ft: ");
scanf("%lf", &rent_rate);
}
return rent_rate;
}
%f is for floating point numbers(e.g. float, double). You should use %d instead.
Also, just like #K-ballo mentioned, your logic is wrong. You should use a do {}while loop, because you'd like to get the input first from the user before making your first choice.
do
{
..
scanf("%d", &rentrate);
}while (rentrate <= 0);
reentrate is declared as integer, I think you want
scanf("%d",&rentrate);
not
scanf("%f",&rentrate);