C fabs returning integer - c

I have a strange problem with fabs function in C code. I have two double values and I want to find the absolute value of their difference using code like this:
a = 87.967498;
b = 218.025015;
if (fabs(a-b)<2.0)
...code to execute
The value of fabs(a-b) is an int and is equal to 1. I don't know whats the problem here and I can't find anything on the net. Any help would be great!!

You didn't include <math.h>. Add the following line to your other includes:
#include <math.h>
In order to find such errors easier I recommend you to use verbose compiler warnings (gcc -Wall -Wextra ... if you use gcc).

The only way that fabs could return an int is either:
Your program uses a declaration of fabs other than the version declared in math.h.
Your program failed to include math.h and so does not declare fabs at all. In which case parameters and return values default to int. Which is of course an error because the actual implementation of fabs does not match and so the value returned is nonsense.

See this code:
#include <math.h>
#include <stdio.h>
int main()
{
float a = 87.967498;
float b = 218.025015;
float diff = a-b;
printf("diff=%f\nfabs(diff)=%f\n",diff,fabs(diff));
if (fabs(diff)<2.0) {
printf("OK\n");
} else {
printf("FAIL\n");
}
return 0;
}
It produces this output:
diego#malti:~/tmp$ clang test-math.c -o test-math -lm
diego#malti:~/tmp$ ./test-math
diff=-130.057510
fabs(diff)=130.057510
FAIL
See? The application is OK, the diff (218-87=130), which is not smaller then 2.
See also then when I am compile, I also link -lm to get the mathematical library. The same syntax applies for gcc, I just love using clang :)

Related

pow() sometimes and sometimes not found w/o -lm switch in gcc

Why does this compile and run this w/o the "-lm" switch on gcc:
#include <stdio.h>
#include <math.h>
int main()
{
printf("2 to the 8th power is %f\n",pow(2.0,8.0));
return(0);
}
but this:
#include <stdio.h>
#include <math.h>
int main()
{
float a,b;
a = 2.0;
b = 8.0;
printf("2 to the 8th power is %f\n",pow(a,b));
return(0);
}
gives the error:
undefined reference to `pow'
unless you link the math library with -lm
The behavior is the same if I use doubles rather than floats. Is there some sort of rudimentary pow() function hidden in standard library, or is the linker just resigned to working with idiots and links the math library for really simple cases?
I'm using gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0 if that makes any difference. It's not a big deal, just curious why that happens, thanks!
I had myself, a problem of understanding, what is wrong with the above. I got the same behaviour with gcc -O0. Running executable with strace and gdb showed that no function call made at all.
Scratched my head, read some comments and got it. Me alone, would have guessed the answer for hours. All credits goes to commenters
Try to change your code to
....
double t = (int)(2.0 + 1.0) % 2 + 1.0;
double r = pow(2.0+t,8.0);
....
With -O0 flag you should hopefully get undefined reference to 'pow' message.

Passing variables to fmax

So I have the following code:
#include <math.h>
int main (void) {
float max = fmax (1.0,2.0);
return 0;
}
Which compiles and runs fine, but if instead of passing 1.0 and 2.0 to the function I pass a, b with those values:
#include <math.h>
int main (void) {
float a = 1.0; float b = 2.0;
float max = fmax (a,b);
return 0;
}
I get the following error:
undefined reference to `fmax'
What is the diffrence? What I'm doing wrong?
I'm using this command to compile:
c99 fmax_test.c
In the first case fmax probably gets optimised away at compile time. In the second case it does not and you then get a link error. Without knowing what compiler you are using it's hard to give a specific remedy, but if it's gcc then you may need to add -lm, e.g.
c99 -Wall fmax_test.c -lm
Note also that fmax is for doubles - you should be using fmaxf for floats.
compile with -lm
i'm using gcc. maybe not OK with your compiler.
try this:
c99 fmax_test.c -lm

Why does this code keep giving this error? Syntax error: Bad for loop variable

This is copied from The C Programming Language By Ritchie. I've tried to make some modifications but it always gets stuck on the for loop (line 7)
#include <stdio.h>
main()
{
int fahr;
for(fahr = 0; fahr <= 300; fahr = fahr + 20)
{
printf("%3d %6.1f\n", fahr, (5.0/9.0)*(fahr-32));
}
}
error: ./farn.c: 8: ./farn.c: Syntax error: Bad for loop variable
I reproduced your problem. On Ubuntu, /bin/sh is symbolically linked to dash.
$ dash ./farn.c
./farn.c: 8: Syntax error: Bad for loop variable
It is very rare for a C program to be correctly interpreted by a Bourne shell interpreter (or one of its derivatives).
Compile the program with a C compiler, and run the executable (alternatively, use a C language interpreter if you can find one). On Ubuntu, you can use gcc:
$ gcc -W -Wall -Werror -pedantic -std=c99 farn.c -o farn
$ ./farn
Since the K&R book predates C.99, the above compilation command will generate an error:
cc1: warnings being treated as errors
farn.c:4: warning: return type defaults to 'int'
To fix this, you can simply update the declaration of main() with an explicit int return type. In C.99, encountering the } at the end of main() implicitly returns 0, so adding int is sufficient.
#include <stdio.h>
int main()
{
int fahr;
for(fahr = 0; fahr <= 300; fahr = fahr + 20)
{
printf("%3d %6.1f\n", fahr, (5.0/9.0)*(fahr-32));
}
}
Other than the fact that you're defining main() in a very lazy way and the lack of a return statement, I don't see anything wrong at all with the code above. After fixing those 2 issues, it compiled and ran just fine with the following options:
gcc temperature.c -g -Wall -Werror -pedantic -o temperature
As an aside, the entry-point to main should be either of:
int main(void) // You *can* leave void out here, but it's best to be explicit
int main(int argc, char* argv[]) // 2nd arg could also be char** argv
And you should always return an integer value from main, usually a return of 0 indicates the program ran successfully.
Your code compiles correctly. This is the proof : http://codepad.org/hryZ2dEm
I have also added the return type and the return instruction in the main function to make your code conform to the standard. Try to use the small changes I have inserted.
Let me know if you still have a problem.
Thank for the advice everyone. I solved my problem by using GCC like a boss.
gcc farn.c -o farn
then
./farn
works great. :-)

Including files in C

I want to make a simple function involving sqrt(), floor() and pow(). So, I included <math.h>. When I try to use my function, my program says that sqrt() and floor() do not exist. I've triple checked my files and rewritten them, but it still gives the same error. Just to check if there was anything wrong with the <math.h> directory, I made another separate file that calculated the same thing and it worked. I am clueless right now. What am I doing wrong?
The code of the non functioning program:
#include <math.h>
#include "sumofsquares.h"
int sumofsquares(int x){
int counter = 0;
int temp = x;
while(temp != 0){
temp = temp - (int)pow(floor(sqrt(temp)), 2);
counter ++;
}
return counter;
}
The working test file:
#include <stdio.h>
#include <math.h>
int main(void){
printf("%d", (int)pow(floor(sqrt(3)), 2));
}
the error is this
/tmp/ccm0CMTL.o: In function sumofsquares':
/home/cs136/cs136Assignments/a04/sumofsquares.c:9: undefined reference
to sqrt' /home/cs136/cs136Assignments/a04/sumofsquares.c:9: undefined
reference to floor' collect2: ld returned 1 exit status`
I am using runC on a virtual Ubuntu OS to compile
You're probably missing the -lm argument to gcc, required to link the math library. Try:
gcc ... <stuff> ... -lm
There are at least two C FAQs relevant to your problem:
14.3
13.26

pow doesn't accept the second parameter to be a variable on gcc

pow doesn't accept the second parameter to be a variable on gcc
The following code works fine on VC++10
// file test.cc
#include "stdafx.h"
#include <stdio.h>
#include <math.h>
int main(void)
{
double x = 10;
int y = 20;
printf("%f\n", pow(x, y));
return 0;
}
But the following code doesn't not work on gcc:
// test.c
#include <stdio.h>
#include <math.h>
int main(void)
{
double x = 10;
int y = 20;
printf("%f\n", pow(x, y)); // error here, says no such function, however when pass the second argument in `pow` for the code runs by gcc, It works fine!
return 0;
}
You're mistaken. It has nothing to do with the second parameter.
In POSIXish systems pow() is in libm, whereas in win32ish systems it is part of the standard C library. That means instead of this:
$ gcc program.c
/tmp/ccTw1gCA.o: In function `main':
program.c:(.text+0x30): undefined reference to `pow'
you need to do this:
$ gcc program.c -lm
The reason it may appear that the second parameter works as a constant but not as a variable is that gcc has a built-in implementation of pow(). If the second parameter is a constant it might be using that where if it's a variable it's falling back on the glibc pow() function. See:
http://gcc.gnu.org/onlinedocs/gcc-4.5.0/gcc/Other-Builtins.html#Other-Builtins
If you pass -fno-builtin to gcc you should see consistent behavior--in this case error messages no matter what you pass to pow(). As others have mentioned whenever you use anything out of math.h you need to link with -lm.

Resources