Math giving incorrect results with value obtained from scanf() - c

I'm trying to write a function that can, given one, convert between to all four of Kilometers, Miles, Nautical Miles, and Furlongs given one of the four. My Main function looks like:
int main() {
Scale scale; // declared in the header file "length.h"
double value, kilometers, miles, nautical_miles, furlongs;
// prompt user for unit to convert from
printf("\nPlease select which unit you want to convert from:\n");
printf("1. Kilometers\n2. Miles\n3. Nautical Miles\n4. Furlongs\n");
scanf("%d", &scale);
// Get value user wants
printf("Enter value for unit you selected: ");
scanf("%d", &value);
int err = convertLength(&kilometers, &miles, &nautical_miles, &furlongs, scale);
printf("value given was %d\n", value);
kilometers *= value;
//kilometers *= 2;
//kilometers = kilometers * value;
printf("%g Kilos\n%g miles\n%g naut mi\n%g fur", kilometers, miles, nautical_miles, furlongs);
return 0;
}
The conversion is taking place in the file "length.c" and I have only been debugging the kilometers case so far. The Enum declaration for scale is in a header file "length.h".
The issue is that when I multiply kilometers in main() by value, I get an incorrect result (such as 4.940e-324). However, when I only multiply by a constant, like the commented out line //kilometers *= 2; I will get the correct answer (2 in that case). What's going wrong with the variable value that's making it behave in this way?
int convertLength(double *kilometers, double *miles, double *nautical_miles, double *furlongs, Scale scale) {
switch(scale) {
case KILOMETERS:
printf("Kilometers was chosen\n");
*kilometers = 1;
*miles = 1/1.609347219;
*nautical_miles = *miles * 1.15078;
*furlongs = *miles / 8;
break;

Change scanf()'s specifier, for double it is "%lf", not "%d", also
Turn on compiler warnings to avoid this kind of mistake, it should warn you about the incompatibility between the passed pointer and the expected pointer.
Check scanf()'s return value to ensure that your data is find instead of just assuming that it is.

Related

Converting km to miles, feet, yards and inches (More detailed question below)

#include <stdio.h>
int main(){
double km, miles, yards, feet, inches;
scanf("%lf", &km);
miles = km/1.609;
printf("%d\n", (int)miles);
yards = ((km*1093.61) - ((int)miles*1760));
printf("%d\n", (int)yards);
feet = (km*3281.4) - ((int)miles*5280 + yards*3);
printf("%d\n", (int)feet);
inches = km*39378.498 - ((int)miles*63360 + (int)yards*36 + (int)feet*12);
printf("%.2lf", inches);
return 0;
}
This is what I managed to write, however it still doesn't pass all tests and isn't 100% accurate as seen in the image below
Help would be highly appreciated.
When writing code to do conversions such as in your task, it is better to do all (internal) calculations in double precision and convert each component part of the result (to int) 'on the fly', then subtract each of those converted values as they are determined.
So, first get the conversion into miles as a double value, then subtract each integral part and multiply the remainder by the factor required to get the next sub-unit. Using this approach, you are far less likely to encounter problems due to integer overflow and rounding errors.
The following is a potential solution. (Note that it is far better to write clear code than attempt to 'compress' many operations into single-line code; the latter is a common cause for bugs creeping into your code and also makes it more difficult for future developers of your code to understand and/or modify it.)
#include <stdio.h>
int main()
{
double km = -1.0, total, inches;
int miles, yards, feet;
do {
printf("Enter value in Km: ");
if (scanf("%lf", &km) != 1) { // Error input: clear buffer
int c;
while ((c = getchar()) != '\n' && c != EOF)
;
if (c == EOF) return 1; // Can't do much after an EOF!
}
} while (km < 0.0);
// First, do the conversion to double "total" ...
total = km / 1.609;
// Now, get the integer "miles" value and subtract that from the total ...
miles = (int)total;
total -= (double)miles;
// Next, multiply remainder by 1760 to get the number of yards ...
total *= 1760.0;
// Now, get the integer value and subtract that from total ...
yards = (int)total;
total -= (double)yards;
// Multiply remainder by 3 to get feet ...
total *= 3.0;
feet = (int)total;
total -= (double)feet;
// Finally, multiply remainder by 12 to get inches ...
inches = total * 12.0;
// Display result:
printf("%d %d %d %.2lf\n", miles, yards, feet, inches);
return 0;
}
Note that I have also added some code to check that the input value is 'acceptable' (I have chosen to reject negative values, but you can easily change that condition); more importantly, the code will also be able to deal with situations where the user enters a value that cannot be interpreted as a floating-point input (like "Fred"). When using scanf for user input, it is always a good idea to check for valid input and handle possible error conditions.

Accounting for a float in C

So I adjusted the code and it seems to work minus one flaw. The shrink is now a float, but not returning the correct answer. when I attempt to shrink 9 for instance it returns 4.0 not 4.5...... 13 returns 6.0? New code is below:
include
int main ()
{
/* variable definition: */
int intValue, menuSelect,Results;
float sResults;
intValue = 1;
// While a positive number
while (intValue > 0)
{
printf ("Enter a positive Integer\n: ");
scanf("%d", &intValue);
if (intValue > 0)
{
printf ("Enter 1 to calculate Square, 2 to Calculate Cube, Enter 3 to Calculate Shrink \n: ");
scanf("%d", &menuSelect);
if (menuSelect == 1)
{
// Call the Square Function
Results = Square(intValue);
printf("Square of %d is %d\n",intValue,Results);
}
else if (menuSelect == 2)
{
// Call the Cube function
Results = Cube(intValue);
printf("Cube of %d is %d\n",intValue,Results);
}
else if (menuSelect == 3)
{
sResults = Shrink(intValue);
printf("shrink of %d is %f\n", intValue,sResults);
}
else
printf("Invalid menu item, only 1 or 2 or 3 is accepted\n");
}
}
return 0;
}
/* function returning the Square of a number */
int Square(int value)
{
return value*value;
}
/* function returning the Cube of a number */
int Cube(int value)
{
return valuevaluevalue;
}
int Shrink(int value)
{
return value*1/2;
}
Results = Shrink(intValue);
printf("shrink of %d is %f\n", intValue,sResults);
You're storing the result in Results, but then printing sResults. Those are two different variables, and sResults is still zero because it hasn't been assigned a value. Change sResults to Results in your printf statement.
However, since you're doing integer division, you'll get a result that's truncated to an integer: Shrink(5) will return 2. To fix that, you'll need to change Shrink to take a float argument instead of int, return float instead of int, and assign its result to sResult instead of Result.
Also, you're probably getting compiler warnings about the Square, Cube, and Shrink functions being undeclared. Those happen because the code that calls the functions is before the code that says what they are. It hasn't caused an actual problem for you yet, because the compiler handles the situation by assuming that each function takes an int argument and returns an int result, which coincidentally happens to be true. But if you change any of the functions to operate on float instead of int, your program will break because the calls will still be compiled as if they were int.
Move the three math functions up above main, or leave them at the bottom and put these lines before main:
int Square(int value);
int Cube(int value);
int Shrink(int value);
Those are called declarations, and they tell the compiler what types the functions operate on, so it knows how to handle them even before it sees their implementation. If you change the functions to operate on float instead of int, change the declarations to match.

stack around variable is corrupted. C visual studio

I am making a program to convert weight and height from metric to US and vice versa. I did the height part successfully, but the part with the weight is giving me a runtime error that stack around variable was corrupted.
I know that happens with arrays because pretty much thats all I get when I google the issue, but this is happening with a regular integer variable in 2 different functions.
This is the function that calls other functions to convert weight, one is for input, one is to convert and one is for output:
void weight_to_metric(void){
int kilograms, pounds;
double grams, ounces;
int * pkilograms= &kilograms, *ppounds=&pounds;
double * pgrams=&grams, *pounces=&ounces;
input_us_weight(ppounds, pounces);
weight_us_to_metric(ppounds, pounces, pkilograms, pgrams);
output_metric_weight(pkilograms, pgrams);
}
this is the function that inputs
void input_us_weight(int* feet, double * inches){
printf("enter the number of pounds you want to convert: ");
scanf(" %lf", feet, "\n");
printf("enter the number of ounces you want to convert: ");
scanf(" %lf", inches, "\n");
}
this is the function that converts
void weight_us_to_metric(int* pounds, double* ounces, int* kilograms, double * grams){
double temp_kilograms;
*kilograms = *pounds / 2.2046 + ((*ounces / 16) / 2.2046);
temp_kilograms = *pounds / 2.2046 + ((*ounces / 16) / 2.2046);
*ounces = ((temp_kilograms - *kilograms) *2.2046)*16;
*grams = ((*ounces / 16.0)/2.2046) * 1000;
}
The output function doesn't even deal with the variable that corrupts. The variable that corrupts is pounds. The integer pounds declared in the initial variable.
How do i fix this?
You are using wrong format specifiers in one of your scanfs. Use %d when scanning an int and %lf when scanning a double. Change
scanf(" %lf", feet, "\n");
to
scanf("%d", feet);
Also, remove the third argument("\n") that you pass to the scanfs. It makes no sense.

input in C programming language

I want code receive from user a floating number but store only two digit after decimal point
for example if user input
a=123.123456789
a value will equal 123.12
#include <stdio.h>
int func(int x,int digit,int con,char* s)
{
int v;
v=x/digit;
v=v*digit;
x-=v;
if(con==1){
printf("%d %s(s) de R$ %.2f\n",(v/digit),s,(float)digit/100);
return x;
}
printf("%d %s(s) de R$ %.2f\n",(v/digit),s,(float)digit);
return x;
}
int main() {
int x=0;
float y;//if change to double the result will be true
scanf("%f",&y);
//y = ((int)(100.0 * y)) / 100.0;
x=(int)y;
y=y-x;
printf("NOTAS:\n");
char* arr="nota";
x=func(x,100,0,arr);
x=func(x,50,0,arr);
x=func(x,20,0,arr);
x=func(x,10,0,arr);
x=func(x,5,0,arr);
x=func(x,2,0,arr);
printf("MOEDAS:\n");
arr="moeda";
x=func(x,1,0,arr);
//mod
x=y*100;
x=func(x,50,1,arr);
x=func(x,25,1,arr);
x=func(x,10,1,arr);
x=func(x,5,1,arr);
x=func(x,1,1,arr);
return 0;
}
problem will found in:
https://www.urionlinejudge.com.br/judge/en/problems/view/1021
If you just want to round off to two decimal points you could try something like:
a = ((int) (a*100))/100.0;
The value have only 2 decimal places is a matter of displaying it, so you just need to print the number of decimal places you are interested in, like
float value = 123.123456;
printf("%.2f\n", value);
if you want to dynamicaly specify that number, you can use
float value = 123.123456;
int decimals = 2;
printf("%.*f\n", decimals, value);
If you want to store the value as a string then use sprintf() or better snprintf().
And taking the input with only two decimals does not make sense anyway because the output is what should be filtered instead of the input, note that after all you will ignore the extra decimals inserted by the user.
Also, note that floating point numbers cannot store exact numbers, so even i you leave only two decimal places by doing something like
float value = ((int)(100.0 * 123.1234156)) / 100.0
the actual value that is stored might be
123.1200000001
which has more decimal places.
One thing that you could try is
struct RealNumber
{
int integerPart;
int decimalPart;
};
and then handle the input to read them separately, which will be really dificult.

I can't get this (simple) loop to work properly

I'm in a programming class right now, and was asked to create a program that calculated the sum of a user's input for multiple numbers--then calculate the nth root of the sum. If the number they input was less than 0, the loop is supposed to discard the less than 0 number, then ask again.
Unfortunately, no matter what number I input--it displays "Value needs to be greater than zero!" I tried putting a fflush(stdin); statement in the loop, but that didn't seem to do anything.
Here is my code. I really appreciate any and all help.
#include "stdafx.h"
#include <stdio.h>
#include <math.h>
int main() {
int mTotalNums, mNth; //amount of numbers in set
float mProd = 1, x, mNroot;
printf("How many numbers are in the set?\n");
scanf("%i", &mTotalNums);
mNth = mTotalNums; //set the value of mTotalNums equal to mNth becuase we'll lose the original value of mTotalNums after the loop
while (mTotalNums > 0) {
printf("Input number: ");
scanf("%lf", &x);
if (x > 0) {
mProd *= x;
} else
printf("\nValue needs to be greater than zero!\n");
}
mNroot = pow(mProd, (1 / mNth));
printf("\nThe nth root of the product of %i terms is: %.2f\n", mNth, mNroot);
return 0;
}
"%lf" is the scanf format for a double, but x is declared as float.
To scan a float, you have to use the %f format.
Note also that mTotalNums is not decremented in the loop, so that it will never
terminate.
Read the documentation of scanf(3). Since x is declared as a float, use %f as the scanf format control string. Also, take into account the result of scanf (it would be 1 if successfully read one item).
You should enable all warnings and debug info in your compiler, then learn how to use the debugger (notably to run your program step by step, display local variables, etc....).
(On Linux, if compiling with gcc -Wall -g you would get a useful warning, and the gdb debugger would be helpful...)
Try these modifications to your program (added comments with changes made)
#include "stdafx.h"
#include <stdio.h>
#include <math.h>
int main() {
//amount of numbers in set
int mTotalNums, mNth;
// Change to double for added precision
double mProd = 1.0, x, mNroot;
printf("How many numbers are in the set?\n");
scanf("%i", &mTotalNums);
// Set the value of mTotalNums equal to mNth becuase
// we'll lose the original value of mTotalNums after the loop
mNth = mTotalNums;
// Don't forget to decrement the loop counter
while (mTotalNums-- > 0) {
printf("Input number: ");
scanf("%lf", &x);
if (x > 0) {
mProd *= x;
} else {
printf("\nValue needs to be greater than zero!\n");
}
}
// Change to 1.0 to force compiler to treat as a double
mNroot = pow(mProd, (1.0 / mNth));
printf("\nThe nth root of the product of %i terms is: %.2f\n", mNth, mNroot);
return 0;
}
You mention "calculate the nth root of the sum", but your loop is clearly tallying the cumulative product. To change it to calculate the sum, try the following additions:
// Declare a sum variable
double sum = 0;
// Sum inside your while loop
sum += x;
// Calculate the nth root of the sum instead
mNroot = pow(sum, (1.0 / mNth));
Add printf commands to see what your variables contain before you check them in your logic statements.
You also need to do something to increment/decrement your variable for your while loop... currently nothing is changing mTotalNums, so it will be an infinite loop.
while (mTotalNums > 0) {
printf("Input number: ");
scanf("%lf", &x);
printf("x=%d", x);
if (x > 0) {
mProd *= x;
} else
printf("\nValue needs to be greater than zero!\n");
mTotalNums--;
}

Resources