I try to check subnormal numbers. Below is my code. It works, but I do not see a difference between Min positive normal number and subnormal number.
Why ?
/*
isnormal example
ISO C99
http://www.cplusplus.com/reference/cmath/isnormal/
http://www.gnu.org/software/libc/manual/html_node/Floating-Point-Classes.html
http://docs.oracle.com/cd/E19957-01/806-3568/ncg_math.html
compile with:
gcc -std=c99 -lm s.c
run :
./a.out
*/
#include <stdio.h> /* printf */
#include <math.h> /* isnormal, fpclassify */
int TestNumber(double x)
{
int f; // flag
f= isnormal(x);
if (f)
printf ("number %f is normal \r",x);
else printf ("number %.1000f is not normal \n",x);
return f;
}
//----------------------------
int main()
{
double d ;
double MinNormal;
int f;
d = 1.0 ; // normal
f = TestNumber(d);
do
{
d /=2.0;
MinNormal=d;
f = TestNumber(d);
}
while (f);
printf ("number %.1000f is minimal normal \n",MinNormal);
printf ("number %.1000e is not normal \n",d);
printf ("number %.1000e is minimal normal \n",MinNormal);
return 0;
}
Here is my output :
gcc -std=c99 -lm s.c
a#acer:~/cnie/numerical/subnormal/s1$ time ./a.out
number 0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111253692925360069154511635866620203210960799023116591527666370844360221740695909792714157950625551028203366986551790550257621708077673005442800619268885941056538899676600116523980507372129181803596078252347125186710418762540332530832907947436024558998429581982425031795438505915243739989044387687497472579022580252545769992829123540932255676896790249605799054288302599621667605717619507439784980479564444580149632075553173315669683173879325651468588102366281589074283217543606141431882102242340570380695573853140084492662205501208072371080928358307527007714254235837645095158066138944836485368656166704349449158753391942346304638698898642932982747054568454770306823378435119933915764534049231 is not normal
number 0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111253692925360069154511635866620203210960799023116591527666370844360221740695909792714157950625551028203366986551790550257621708077673005442800619268885941056538899676600116523980507372129181803596078252347125186710418762540332530832907947436024558998429581982425031795438505915243739989044387687497472579022580252545769992829123540932255676896790249605799054288302599621667605717619507439784980479564444580149632075553173315669683173879325651468588102366281589074283217543606141431882102242340570380695573853140084492662205501208072371080928358307527007714254235837645095158066138944836485368656166704349449158753391942346304638698898642932982747054568454770306823378435119933915764534049231 is minimal normal
number 1.1125369292536006915451163586662020321096079902311659152766637084436022174069590979271415795062555102820336698655179055025762170807767300544280061926888594105653889967660011652398050737212918180359607825234712518671041876254033253083290794743602455899842958198242503179543850591524373998904438768749747257902258025254576999282912354093225567689679024960579905428830259962166760571761950743978498047956444458014963207555317331566968317387932565146858810236628158907428321754360614143188210224234057038069557385314008449266220550120807237108092835830752700771425423583764509515806613894483648536865616670434944915875339194234630463869889864293298274705456845477030682337843511993391576453404923086054623126983642578125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-308 is not normal
number 1.1125369292536006915451163586662020321096079902311659152766637084436022174069590979271415795062555102820336698655179055025762170807767300544280061926888594105653889967660011652398050737212918180359607825234712518671041876254033253083290794743602455899842958198242503179543850591524373998904438768749747257902258025254576999282912354093225567689679024960579905428830259962166760571761950743978498047956444458014963207555317331566968317387932565146858810236628158907428321754360614143188210224234057038069557385314008449266220550120807237108092835830752700771425423583764509515806613894483648536865616670434944915875339194234630463869889864293298274705456845477030682337843511993391576453404923086054623126983642578125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-308 is minimal normal
================edit===============
good program after applaying all the changes from the answers and comments
while (f)
{
MinNormal=d;
d /=2.0;
f = TestNumber(d);
}
and print only 16 digits:
printf ( "number %.16e is normal \n",x);
The way your loop is written, it always ends with d and MinNormal set to the same value. You should move the assignment of MinNormal before the change to d so that it remembers the value of d from the previous iteration.
Related
#include<stdio.h>
int cube(int n)
{
return (n*n*n);
}/*function to return cubic root*/
int sumcube(int x)
{
int sum=0,m;
while(x>0)
{
m=x%10;
sum=sum+(cube(m));
x=x/10;
}
return sum;
}/* returns the sum if cubic digits of an integer*/
int main ()
{
int i;
for(i=1; i<=5000; i++)
{
if (i==sumcube(i));
{
printf("%d\t",i);
}
}
}
/* this program is to check wether a number is an armestrong from 1 to 5000 as well as to check the output was all the integers from 1 to 5000*/
You have a ; after the if, this is interpreted as an empty body for the if and therefore everything after it will be executed regardless if the condition in the if-statement is true or not.
To avoid the same error in the future, enable all compiler warnings and only disable the warnings you are sure you want to ignore and set the treat warnings as error flag for development (not when you release code, but that is not something you should do at your knowledge level). For gcc use the flags -Wall -Wextra -Wpedantic -Werror. With that, the compiler generates an error for your code.
I am writing a function in C with the below specifications:
float find_root(float a, float b, float c, float p, float q);
find_root takes the coefficients a,b,c of a quadratic equation and an interval (p, q). It will return the root of this equation in the given interval.
For example: find_root(1, -8, 15, 2, 4) should produce a root "close to" 3.0
I have written the below code, and I don't understand why it doesn't work:
#include<stdio.h>
#include<math.h>
main()
{
printf("Hello World");
}
float find_root(float a, float b, float c, float p, float q) {
float d,root1,root2;
d = b * b - 4 * a * c;
root1 = ( -b + sqrt(d)) / (2* a);
root2 = ( -b - sqrt(d)) / (2* a);
if (root1<=q || root1>=p)
{
return root1;
}
return root2;
}
Please let me know what the error is.
Your program doesn't work, because, you never called find_root() from your main().
find_root() is not suppossed to run all-by-itself. Your program statrs execution from main(). You need to call your sub-function from main() in order to make them execute.
Change your main to have a call to find_root(), something like below.
int main() //put proper signature
{
float anser = 0;
answer = find_root(1, -8, 15, 2, 4); //taken from the question
printf("The anser is %f\n", answer); //end with a \n, stdout is line buffered
return 0; //return some value, good practice
}
Then, compile the program like
gcc -o output yourfilename.c -lm
Apart from this, for the logical issue(s) in find_root() function, please follow the way suggested by Mr. #paxdiablo.
For that data, your two roots are 5 and 3. With p == 2 and q == 4:
if (root1<=q || root1>=p)
becomes:
if (5<=4 || 5>=2)
which is true, so you'll get 5.
The if condition you want is:
if ((p <= root1) && (root1 <= q))
as shown in the following program, that produces the correct 3:
#include<stdio.h>
#include<math.h>
float find_root (float a, float b, float c, float p, float q) {
float d,root1,root2;
d = b * b - 4 * a * c;
root1 = ( -b + sqrt(d)) / (2* a);
root2 = ( -b - sqrt(d)) / (2* a);
if ((p <= root1) && (root1 <= q))
return root1;
return root2;
}
int main (void) {
printf ("%f\n", find_root(1, -8, 15, 2, 4));
return 0;
}
That's the logic errors with your calculations of the roots.
Just keep in mind there are other issues with your code.
You need to ensure you actually call the function itself, your main as it stands does not.
It also wont produce a value within the p/q bounds, instead it will give you the first root if it's within those bounds, otherwise it'll give you the second root regardless of its value.
You may want to catch the situation where d is negative, since you don't want to take the square root of it:
a = 1000, b = 0, c = 1000: d <- -4,000,000
And, lastly, if your compiler is complaining about not being able to link sqrt (as per one of your comments), you'll probably find you can fix that by specifying the math library, something like:
gcc -o myprog myprog.c -lm
Your program starts at main by definition.
Your main function is not calling find_root but it should.
You need to compile with all warnings & debug info (gcc -Wall -Wextra -g) then use a debugger (gdb) to run your code step by step to understand the behavior of your program, so compile with
gcc -Wall -Wextra -g yoursource.c -lm -o yourbinary
or with
clang -Wall -Wextra -g yoursource.c -lm -o yourbinary
then learn how to use gdb (e.g. run gdb ./yourbinary ... and later ./yourbinary without a debugger)
Then you'll think and improve the source code and recompile it, and debug it again. And repeat that process till you are happy with your program.
BTW, you'll better end your printf format strings with \n or learn about fflush(3)
Don't forget to read the documentation of every function (like printf(3) ...) that you are calling.
You might want to give some arguments (thru your main(int argc, char**argv) ...) to your program. You could use atof(3) to convert them to a double
Read also about undefined behavior, which you should always avoid.
BTW, you can use any standard C compiler (and editor like emacs or gedit) for your homework, e.g. use gcc or clang on your Linux laptop (then use gdb ...). You don't need a specific seashell
Change this condition
if (root1<=q || root1>=p)
to
if (root1<=q && root1>=p)
otherwise if anyone of the conditions is satisfied, root1 will be returned and root2 will almost never be returned. Hope this fixes your problem.
I'm trying to call C functions using fortran (need this for a project).
So first was trying to simply call a non parametrized, void function via fortran.
Kindly help me resolve the following errors in the given code.
C Code for matrix multiplication:
#include <stdio.h>
extern "C"
{ void __stdcall mat();
}
void mat()
{
int m, n, p, q, c, d, k, sum = 0;
printf("Enter the number of rows and columns of first matrix\n");
scanf("%d%d", &m, &n);
int first[m][n];
printf("Enter the elements of first matrix\n");
for ( c = 0 ; c < m ; c++ )
for ( d = 0 ; d < n ; d++ )
scanf("%d", &first[c][d]);
printf("Enter the number of rows and columns of second matrix\n");
scanf("%d%d", &p, &q);
int second[p][q];
if ( n != p )
printf("Matrices with entered orders can't be multiplied with each other.\n");
else
{
printf("Enter the elements of second matrix\n");
for ( c = 0 ; c < p ; c++ )
for ( d = 0 ; d < q ; d++ )
scanf("%d", &second[c][d]);
int multiply[m][q];
for ( c = 0 ; c < m ; c++ )
{
for ( d = 0 ; d < q ; d++ )
{
for ( k = 0 ; k < p ; k++ )
{
sum = sum + first[c][k]*second[k][d];
}
multiply[c][d] = sum;
sum = 0;
}
}
printf("Product of entered matrices:-\n");
for ( c = 0 ; c < m ; c++ )
{
for ( d = 0 ; d < q ; d++ )
printf("%d\t", multiply[c][d]);
printf("\n");
}
}
}
int main()
{
mat();
return 0;
}
Also, the code for calling the function mat from fortran that I wrote is :
program mat_mult !This is a main program.
call mat()
stop
end
On executing the C file I get the following error:
matrix_mult.c:5: error: expected identifier or ‘(’ before string constant
On executing the fortran file using the F77 compiler, I get the following error:
/tmp/ccQAveKc.o: In function MAIN__':
matrix_mult.f:(.text+0x19): undefined reference tomat_'
collect2: ld returned 1 exit status
Kindly help me in identifying the error/correct code.
Thank you.
A few things first
1) I'm assuming you're using a C99 compiler because the C code you've written will not work on a C89 compiler.
2) extern "C" is for C++ programs: not C programs.
Not really sure which compiler you're using. Just assuming you're using gcc and gfortran since it looks like you're on a Linux based system.
gcc just adds a leading _ to the symbols: so mat becomes _mat.
gfortran adds both a leading and trailing _ to the symbols: so mat becomes _mat _.
To make C and Fortran talk
a) Remove the main function from the C code
b) Remove extern "C" declaration. This is a C++ declaration that tells the compiler that the routine mat should not have any name mangling.
c) Since you don't have any parameters, just assume _cdecl and change void mat() to void mat(). If you have to use stdcall, then you need to compile with --enable-stdcall-fixup. stdcall will be needed if the Fortran program has to pass parameters to the C program but that is a different ball game. Instead of _mat _, the compiler generates mat#0
d) Your C routine will now look like
#include <stdio.h>
void mat_()
{
...
}
/* No main */
e) Since the routine mat is not declared in the Fortran code, the compiler needs to know that it is external.
program mat_mult
external mat
call mat()
stop
end
f) Compile and link (say the C program is called mat.c and the fortran program is called matmul.f)
gcc -g -c mat.c
gfortran -g matmul.f mat.o -o matmul
There will probably be a whole load of comments recommending that you use F2003 or F2008 but if you have been told that you have to use F77, then you have to use F77.
/tmp/ccjiJKv2.o: In function func':
b.c:(.text+0x16b): undefined reference tosqrt'
collect2: ld returned 1 exit status
Here is the code and I am using gcc compiler..
/*Write a function that receive 5 integers and returns the sum,average and standard deviation of these numbers*/
/*Author:Udit Gupta Date:10/08/2011*/
#include<stdio.h>
#include<math.h>
void func (int *,float *,float *);
int main () {
float avg,std_dev;
int sum;
func (&sum,&avg,&std_dev); /*Passing address of variables where output will be stored.....*/
printf ("The sum of numbers is %d\n",sum);
printf ("The average of numbers is %f\n",avg);
printf ("The standard deviation of numbers is %f\n",std_dev);
}
void func (int *sum_, float *avg_ , float * std_dev_) {
int n1,n2,n3,n4,n5;
printf("Please enter the number:");
scanf("%d%d%d%d%d",&n1,&n2,&n3,&n4,&n5);
/*Formula for sum,average and standard deviation*/
*sum_ = n1+n2+n3+n4+n5; /*Writing output at the address specified by arguments of function*/
*avg_ = *sum_ / 5 ;
*std_dev_ = sqrt ( pow((n1-*avg_),2)+pow((n2-*avg_),2)+pow ((n3-*avg_),2)+pow ((n4-*avg_),2)+pow ((n5-*avg_),2)/4) ;
}
You are not linking the library which contains the implementation of sqrt.
That library is known as "libm" (the math library), and can be linked to as follows:
gcc -o myprog infile.c -lm
#include <math.h> - is this what you need?
Also, Link with -lm
you have to link the math library. -lm
I wrote a function named absD that i want to return the absolute value of its argument..
I am using GCC inline assembly with cygwin..
I dont see why its not working. i m loading into memory. then into st(0)
where i am using fabs - absolute value. Do i have to allocate memory?
I am trying to learn assembly with C here so please be nice. Please give me good help.
Thank you
heres the code and then the error:
#include <stdio.h>
#include <stdlib.h>
#define PRECISION 3
double absD (double n)
{
asm(
"fldl %[nIn]\n"
"fabs\n"
"fstpl %[nOut]\n"
: [nOut] "=m" (n)
: [nIn] "m" (n)
);
return n;
}
int main (int argc, char **argv)
{
double n = 0.0;
printf("Absolute value\n");
if (argc > 1)
n = atof(argv[1]);
printf("abs(%.*f) = %.*f\n", PRECISION, n, PRECISION, absD(n));
return 0;
}
here is the output:
~ $ gc a3
gcc -Wall -g a3.c -o a3
~ $ ./a3
Absolute value
abs(0.000) = 0.000
~ $
Not outputing its absolute value...
Thank you..
It is completely working..!! You are just forgetting to put values to argv. You can run the program with something like this:
./a3 -1.3
and it should return 1.3
you were done before posting it here...
fld (%eax) means "load a float from the value at address %eax". Obviously, the contents of %eax are a double, and not a pointer to a float, which is why you segfault.
Since the input is already on the stack (thus it has an address), there's no need to jump through hoops moving things around.
double absD(double input) {
double output;
asm(
"fldl %[input]\n"
"fabs\n"
"fstpl %[output]\n"
: [output] "=m" (output)
: [input] "m" (input)
);
return output;
}
Also, your printf format is wrong: %f means float, but you're giving it a double; you want to use %g.