Casting float to int doesn't work properly in C - c

I tried to solve a task on codewars and happened something strange, in one case casting worked as usual and in the second o got strange behavior. Here is the code:
#include <stdio.h>
#include <string.h>
#include <math.h>
int digital_root(int n) {
char tmp[30];
char *ptr;
while(n > 9){
sprintf(tmp, "%d", n);
int len = strlen(tmp);
float n_tmp = n / (pow(10, len));
n = 0;
for(int i = 1; i <=len; i++){
float t = n_tmp * (pow(10, i));
printf(" vars = [%f , %d] ", t, (int)t); //this line
n += (int) t;
n_tmp -= (int)t/pow(10,i);
}
}
return n;
}
int main()
{
digital_root(16);
return 0;
}
And the line printf(" vars = [%f , %d] ", t, (int)t); outputs: vars = [1.600000 , 1] vars = [6.000000 , 5], what is so strange. Can someone explain this behavior?

Every casting float to int is a rounding, so every time you do it, stop for a second and think: what kind of rounding do I need this time? Dropping the fractional part? floor()? ceil()? Or rounding positive float towards nearest int? If 5.999999999999 should be 6, use (int)(t+.5), not (int)t.
Or you can mimic the printf behavior and round only the smallest float fraction, which can vary (depending on the biggest value you use). (int)(t+.000001) will round both 1.9 to 1 (as it probably should), and 3.9999999999 to 4 (because it is 4 with some tiny number representation errors).
You should however know the size of a fraction which can be an actual, meaningful part of your data. Everything smaller than this fraction must be rounded. It can be either .00000001 or .5, that depends on your needs and the algorithm itself.

Related

how do i print out the avarage of several arrays with float?

i'm just starting with getting to know C, and i'm now following the cs50 course. i have a question on the following code.
I want to calculate the avarage score of the user input.
#include <cs50.h>
#include <stdio.h>
int main(void)
{
int s = get_int("how many scores? ");
int sum = 0;
int score[s];
for(int i = 0; i < s; i++)
{
score[i] = get_int("score: ");
sum = sum + score[i];
}
float avg = sum / s;
printf("avarage: %f\n", avg);
}
So, it prints the avarage, but gets round down to .0000.
Is it because i am using a int to divide by? i have tried several things, like changing int to float, but without result.
How do I solve this?
This is an integer division:
float avg = sum / s;
Which means that 3 / 2 will be 1 (the decimal part is discarded). This will then be stored in avg as 1.f.
You need to make it into a floating point division. You can cast one of the operands to the desired type:
float avg = (float)sum / s;
Now both operands (sum and s) will be converted to float before the actual division takes place and the correct result will be shown, which is 1.5 + some zeroes in the example above.
#Ted's answer (integer division) is the reason your results were not as expected.
For your consideration, I've rewritten your code to be more concise. (The less code there is, the easier it can be to read and understand (as you learn more about C.))
#include <cs50.h>
#include <stdio.h>
int main() // 'void' is unnecessary
{
double sum = 0.0; // make the accumulator floating point
int s = get_int( "how many scores? " );
for(int i = 0; i < s; i++) // no need for braces when...
sum += get_int( "score: " ); // everything happens on one line
/* Above: you may not have seen "+=" before. Find out. Aids clarity */
printf("avarage: %lf\n", sum / s ); // float division result is printed.
}
And, the same thing again to compare without comments
#include <cs50.h>
#include <stdio.h>
int main()
{
double sum = 0.0;
int s = get_int( "how many scores? " );
for(int i = 0; i < s; i++)
sum += get_int( "score: " );
printf("avarage: %lf\n", sum / s );
}

Weird compilation issues

#include <stdlib.h>
#include <math.h>
#include <stdio.h>
int rev (int N);
int rev(int N){
return ((N <= 9)) ? N : rev(N / 10) + ((N % 10) * (pow(10, (floor(log10(abs(N))))))) ;
}
int main(void){
int r, n;
scanf("%d", &n);
r = rev(n);
printf("%d %d", r, n);
return EXIT_SUCCESS;
}
A simple code just to find out the reverse of a number. Everything is fine. Until I put a number with more than 2 digits. Things behave weirdly, somehow the last digit is always 0 of the reversed number. I have checked out in online compilers where things behave just fine. However the problem arises when I run the code on my own machine. I am on Windows 10 with MINGw. Could you guys suggest me a solution. I previously had problems where the value stored in an int matrix changes to huge values which is practically impossible to store in int due to it's size.
Using the pow and floor function, working with floats will not always round the way you'd expect.
As already commented, work with integers.
Propose doing this digit-by-digit, and sticking with integers. A proposal for your rev() function:
int rev(unsigned int N)
{
unsigned int res = 0;
while(N>0)
{
// pick off lowest digit
unsigned int digit = N%10;
// put into result, moving up all previous digits by doing *10
res = 10*res+digit;
// remove this digit from input value
N/=10;
}
return res;
}

<math.h> pow() giving wrong result

This is from google's code jam, practice problem "All your base".
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
long long pow_longlong(int digit, int raiseto)
{
if (raiseto == 0) return 1;
else return digit * pow_longlong(digit, raiseto - 1);
}
long long base10_with_map(int base, char* instr, char* digits)
{
if (base < 2) base = 2;
long long result = 0;
int len = strlen(instr);
int i = 0;
while (len--)
result += digits[instr[len]] * pow_longlong(base, i++);
return result;
}
long long test(char* in)
{
char appear[256];
int i;
int len = strlen(in);
int hold = 0;
for (i = 0; i < 256; i++) appear[i] = '\xFF';
for (i = 0; i < len; i++)
if (appear[in[i]] == '\xFF')
{
if (hold == 0) { appear[in[i]] = 1; hold++; }
else if (hold == 1) { appear[in[i]] = 0; hold++; }
else appear[in[i]] = hold++;
}
return base10_with_map(hold, in, appear);
}
int main(int argc, char* argv[])
{
if (argc < 2)
{
printf("Usage: %s <input-file> \n", argv[0]); return 1;
}
char buf[100];
int a, i;
FILE* f = fopen(argv[1], "r");
fscanf(f, "%d", &a);
long long result;
for (i = 1; i <= a; i++)
{
fscanf(f, "%s", buf);
result = test(buf);
printf("Case #%d: %lld\n", i, result);
}
return 0;
}
This works as intended and produces correct result to the problem. But if I replace my own pow_longlong() with pow() from math.h some calculations differ.
What is the reason to this? Just curious.
Edits:
- No overflow, plain long is enough to store the values, long long is just overkill
- Of course I include math.h
- In example: test("wontyouplaywithme") with pow_longlong returns 674293938766347782 (right) and with math.h 674293938766347904 (wrong)
Sorry that I won't go through your example and your intermediary function; the issue you're having occurs due to double being insufficient, not the long long. It is just that the number grows too large, causing it to require more and more precision towards the end, more than double can safely represent.
Here, try this really simple programme out, or just trust in the output I append to it to see what I mean:
#include <stdio.h>
int main( ){
double a;
long long b;
a = 674293938766347782.0;
b = a;
printf( "%f\n", a );
printf( "%lld", b );
getchar( );
return 0;
}
/*
Output:
674293938766347780.000000
674293938766347776
*/
You see, the double may have 8 bytes, just as much as the long long has, but it is designed so that it would also be able to hold non-integral values, which makes it less precise than long long can get in some cases like this one.
I don't know the exact specifics, but here, in MSDN it is said that its representation range is from -1.7e308 to +1.7e308 with (probably just on average) 15 digit precision.
So, if you are going to work with positive integers only, stick with your function. If you want to have an optimized version, check this one out: https://stackoverflow.com/a/101613/2736228
It makes use of the fact that, for example, while calculating x to the power 8, you can get away with 3 operations:
...
result = x * x; // x^2
result = result * result; // (x^2)^2 = x^4
result = result * result; // (x^4)^2 = x^8
...
Instead of dealing with 7 operations, multiplying them one by one.
pow (see reference) is not defined for integers, but only for floating point numbers. If you call pow with int as an argument the result will be a double.
You can in general not assume that the result of pow will be exactly the same as if you would use pure integer math as in the function pow_longlong.
Citation from wikipedia about double precision floating point numbers:
Between 2^52=4,503,599,627,370,496 and 2^53=9,007,199,254,740,992 the
representable numbers are exactly the integers. For the next range,
from 2^53 to 2^54, everything is multiplied by 2, so the representable
numbers are the even ones, etc.
So you get inaccurate results with pow if the result would be bigger than 2^53.

How I can Gave The Variable To The Array in c [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I am trying to solve a problem, I have one integer variable such as
unsigned int x = 456;
Now I want to decompose my integer to an array of its digits, like so:
unsigned int i[] = {4,5,6};
Then I want to convert each element of the array to a string or char.
Any ideas?
I use Avr studio
#include <stdio.h>
int main(){
unsigned int x = 456;
int len = snprintf(NULL, 0, "%u", x);
unsigned int i[len];
unsigned int wk = x;
for(int k=len-1;k>=0;--k, wk/=10)
i[k]=wk % 10;
for(int k=0;k<len;++k)
printf("%u", i[k]);
char string[len+1];
for(int k=0;k<len;++k)
sprintf(string+k, "%u", i[k]);
printf("\n%s\n", string);
return 0;
}
The easiest way to convert an integer to a string is to use a library function such as snprintf().
If you don't have the standard C library, you can use the classic remainder/division trick:
void uint_to_string(char *buf, unsigned int x, unsigned int digits)
{
buf[digits] = '\0';
while(digits > 0)
{
buf[--digits] = '0' + (x % 10);
x /= 10;
}
}
Note that the above builds the string "backwards" (right to left) since that's easiest. It will generate a 0-padded result, you can fix that by adding code to break out of the loop (after the digit is generated on the first line of the loop's body) if x == 0.
main()
{
unsigned int x = 456;
char i[3];
int j,k;
for (j=0; x!=0; j++){
i[j] = x%10 + '0';
x /= 10;
}
for (k=0; k<j; k++)
printf("%c ", i[k]);
return 0;
}
The answer to this is slightly dependent on your actual problem. Do you need the array of digits, or is this merely the intermediate step you yourself came up with to convert an unsigned integer to a string?
If all you need is the string, it would be much simpler to use a function such as sprintf or snprintf.
#include <stdio.h>
//...
unsigned int x = 456;
char digits[50]; // 50 is chosen arbitrarily
snprintf(digits, 50, "%u", x);
//...
Will yield a null-terminated string in digits that looks exactly like the string representation of x, with the caveat that if x is more than 50 digits it will just do as much as it can. (Though I'm not sure an unsigned int can even have more than 50 decimal digits off the top of my head)
If you want the char* to be exactly the correct size to hold the number, it's only a little more difficult.
#include <stdio.h>
// ...
unsigned int x = 456;
int numDigits = snprintf(NULL, 0, "%u", x); // snprintf returns the number of characters that could potentially be written.
char digits[numDigits];
sprintf(digits, "%u", x);
// ...
Without the standard library available, it gets a bit more hairy, but not unmanageably so. Unfortunately, you're going to need two passes that do almost exactly the same things: one to count the digits and one to actually assign them to your array.
int main( void ) {
// ...
unsigned int x = 456;
int numDigits = countDigits(x);
char digits[numDigits+1]; // The +1 is for null-termination
fillDigitArray(digits, x, numDigits);
// ...
}
int fillDigitArray(char *digits, int x, int numDigits) {
int i;
// This requires perhaps a little explaining
// By far the easiest way to get individual digits of a number is with
// x % 10, but this gives us the righthand-most digits
// Thus by counting DOWN, we're filling our buffer from the RIGHT
// making up for the "backwards" nature.
digits[numDigits] = 0;
for (i = numDigits-1; i >= 0; i--) {
digits[i] = '0' + (x%10);
x /= 10;
}
}
int countDigits(int x) {
// Special case
if( x == 0 ) {
return 1;
}
int numDigits;
while(x > 0) {
x /= 10;
numDigits++;
}
return numDigits;
}
Extracting it into an array of unsigned ints is similar, just make digits an unsigned int * rather than a char *, and instead of making digits[i] = '0' + x%10 make it digits[i] = x%10.
Edit: In the interest of fully explaining the example, x%10 is "x mod 10", which can roughly be stated as "give me the rightmost digit of x". x /= 10, while dividing x by 10 and overwriting x with the new value, is essentially just our way of saying "make the right-most digit of x what is currently in the 10's place".
The '0'+ x%10 part is admittedly a bit of magic. The actual ASCII character value for the number "0" isn't actually 0, but the digits 0-9 are laid out in order. So if the rightmost digits of x is 0, we get '0'+0, which is '0', and if we get the rightmost digit as 9 '0'+9' becomes '9'. Using this allows us to bypass an ugly if or switch statement to map the number to the right character.
Getting each digit is a math/logic problem. You need to use the modulus operator which gives you the remainder of the division of the operands.
#include <stdio.h>
static char digits[10];
int main(void) {
int number = 4056;
int remainder = 0;
int i = 0;
while(number > 0 && digits[i] >= 0) {
remainder = number % 10;
number /= 10;
digits[i] = 48 + remainder;
i++;
}
for(i--; i >= 0; i--) {
printf("%c", digits[i]);
}
printf("\n");
}

How to extract the decimal part from a floating point number in C?

How can we extract the decimal part of a floating point number and store the decimal part and the integer part into two separate integer variables?
You use the modf function:
double integral;
double fractional = modf(some_double, &integral);
You can also cast it to an integer, but be warned you may overflow the integer. The result is not predictable then.
Try this:
int main() {
double num = 23.345;
int intpart = (int)num;
double decpart = num - intpart;
printf("Num = %f, intpart = %d, decpart = %f\n", num, intpart, decpart);
}
For me, it produces:
Num = 23.345000, intpart = 23, decpart = 0.345000
Which appears to be what you're asking for.
The quick "in a nut shell" most obvious answer seems like:
#define N_DECIMAL_POINTS_PRECISION (1000) // n = 3. Three decimal points.
float f = 123.456;
int integerPart = (int)f;
int decimalPart = ((int)(f*N_DECIMAL_POINTS_PRECISION)%N_DECIMAL_POINTS_PRECISION);
You would change how many decimal points you want by changing the N_DECIMAL_POINTS_PRECISION to suit your needs.
I created a subroutine one using a double float, it returns 2 integer values.
void double2Ints(double f, int p, int *i, int *d)
{
// f = float, p=decimal precision, i=integer, d=decimal
int li;
int prec=1;
for(int x=p;x>0;x--)
{
prec*=10;
}; // same as power(10,p)
li = (int) f; // get integer part
*d = (int) ((f-li)*prec); // get decimal part
*i = li;
}
void test()
{
double df = 3.14159265;
int i,d;
for(int p=2;p<9;p++)
{
double2Ints(df, p, &i,&d); printf("d2i (%d) %f = %d.%d\r\n",p, df,i,d);
}
}
I think that using string is the correct way to go in this case, since you don't know a priori the number of digits in the decimal part. But, it won't work for all cases (e.g. 1.005), as mentioned before by #SingleNegationElimination. Here is my take on this:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char s_value[60], s_integral[60], s_fractional[60];
int i, found = 0, count = 1, integral, fractional;
scanf("%s", s_value);
for (i = 0; s_value[i] != '\0'; i++)
{
if (!found)
{
if (s_value[i] == '.')
{
found = 1;
s_integral[i] = '\0';
continue;
}
s_integral[i] = s_value[i];
count++;
}
else
s_fractional[i - count] = s_value[i];
}
s_fractional[i - count] = '\0';
integral = atoi(s_integral);
fractional = atoi(s_fractional);
printf("value = %s, integral = %d, fractional = %d\n",
s_value, integral, fractional);
return 0;
}
Use the floating number to subtract the floored value to get its fractional part:
double fractional = some_double - floor(some_double);
This prevents the typecasting to an integer, which may cause overflow if the floating number is very large that an integer value could not even contain it.
Also for negative values, this code gives you the positive fractional part of the floating number since floor() computes the largest integer value not greater than the input value.
Here is another way:
#include <stdlib.h>
int main()
{
char* inStr = "123.4567"; //the number we want to convert
char* endptr; //unused char ptr for strtod
char* loc = strchr(inStr, '.');
long mantissa = strtod(loc+1, endptr);
long whole = strtod(inStr, endptr);
printf("whole: %d \n", whole); //whole number portion
printf("mantissa: %d", mantissa); //decimal portion
}
http://codepad.org/jyHoBALU
Output:
whole: 123
mantissa: 4567
float num;
int intgPart;
float fracPart;
printf("Enter the positive floating point number: ");
scanf("%f", &num);
intgPart = (int)num;
fracPart = num - intgPart;
The fractional part can be obtained by subtracting an integral part from the original double value.
Maybe the best idea is to solve the problem while the data is in String format. If you have the data as String, you may parse it according to the decimal point. You extract the integral and decimal part as Substrings and then convert these substrings to actual integers.
I made this function, it seems to work fine:
#include <math.h>
void GetFloattoInt (double fnum, long precision, long *pe, long *pd)
{
long pe_sign;
long intpart;
float decpart;
if(fnum>=0)
{
pe_sign=1;
}
else
{
pe_sign=-1;
}
intpart=(long)fnum;
decpart=fnum-intpart;
*pe=intpart;
*pd=(((long)(decpart*pe_sign*pow(10,precision)))%(long)pow(10,precision));
}
If you just want to get the first decimal value, the solution is really simple.
Here's an explanatory example:
int leftSideOfDecimalPoint = (int) initialFloatValue; // The cast from float to int keeps only the integer part
int temp = (int) initialFloatValue * 10;
int rightSideOfDecimalPoint = temp % 10;
Say for example we have an initial float value of 27.8 .
By just casting the initial float value to an int, you discard the fraction part and only keep the integer part.
By multiplying the initial float value by 10 we get a result of 278.0, then by casting this result to int, gives you the value of 278
If we divide 278 by 10, we get 27.8, of which the remainder is 8, which is the value at the right side of the decimal point. Thus use modulus.
This technique can then be used to get the following decimal characters by using for example 100 instead of 10, and so on.
Just take note that if you use this technique on real-time systems, for example to display it on a 7-segment display, it may not work properly because we are multiplying with a float value, where multiplication takes a lot of overhead time.
#include <stdio.h>
Int main ()
{
float f=56.75;
int a=(int)f;
int result=(f-a)*100;
printf ("integer = %d\n decimal part to integer
=%d\n",result);
}
Output:-
integer =56
decimal part to integer = 75
Suppose A is your integer then (int)A, means casting the number to an integer and will be the integer part, the other is (A - (int)A)*10^n, here n is the number of decimals to keep.
My printf() didn't support formatting for floats. This was my solution to print it as two integers. Change 100 in to what you like to increase the precision.
I found this one
#define DEC(f) (uint32_t)(100*((f)-(float)((uint32_t)(f))))
#define INT(f) (uint32_t)(f)
DEC(3.1416..) = 14 (int)
INT(3.1416..) = 3 (int)
Let me know what you think of this solution.
Even I was thinking how to do it. But I found a way.
Try this code
printf("Enter a floating number");
scanf("%d%c%d", &no, &dot, &dec);
printf("Number=%d Decimal part=%d", no, dec);
Output:-
Enter a floating number
23.13
Number=23 Decimal part=13
cout<<"enter a decimal number\n";
cin>>str;
for(i=0;i<str.size();i++)
{
if(str[i]=='.')
break;
}
for(j=i+1;j<str.size();j++)
{
cout<<str[j];
}

Resources