I have written the following sample code to find the harmonic value of N. (1+1/2+1/3+...1/N). Read the comments in the code written in BOLD and help me to find why is this happening.
#include <stdio.h>
float harmonic(float n, float har) {
if(n==0) {
return 0;
}
if(n==1) {
printf("%f\n", har+1.0f);***/* This prints value 1.5000*/***
return har+1.0f;
}else{
harmonic(n-1, (har+(1/n)));
}
}
int main()
{
printf("%f\n", harmonic(2, 0.0f)); **/* But this prints value nan(Not a Number)*/**
return 0;
}
Thanks,
Naga
I think you want to do:
return harmonic(n-1, (har+(1/n)));
My first thought was that you should almost never compare floats with simple equality so "if(n==0)" should be "if(n<=EPSILON)" and "if(n==1)" should be "if(n<= 1.0f + EPSILON)" where EPSILON is a small positive fraction, maybe 1.0e-5. Depends on how much precision you can depend on.
But then I realized that n should be an int. Cast it to a float before the division. As the comparisons with "n" stand you risk infinite recursion.
Consider using a double instead of a float.
Matthew Flaschen's answer gets to real reason you get the NaN message. The original code doesn't return anything from the "else" so the caller is probably reading garbage from the stack. Hence, the NaN.
Related
I have written an atof() implementation in c . I am facing rounding off errors in this implementation . So , putting in a test value of 1236.965 gives a result of 1236.964966 but the library atof() function reurns 1236.965000 . My question is , how to make the user defined atof() implementation more 'correct' ?
Can the library definition of atof() be found somewhere ?
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
float str_to_float(char *);
void float_to_str(float,char *);
int main(){
int max_size;
float x;
char *arr;
printf("Enter max size of string : ");
scanf("%d",&max_size);
arr=malloc((max_size+1)*sizeof(char));
scanf("%s",arr);
x=str_to_float(arr);
printf("%f\n%f",x,atof(arr));
return 0;
}
float str_to_float(char *arr){
int i,j,flag;
float val;
char c;
i=0;
j=0;
val=0;
flag=0;
while ((c = *(arr+i))!='\0'){
// if ((c<'0')||(c>'9')) return 0;
if (c!='.'){
val =(val*10)+(c-'0');
if (flag == 1){
--j;
}
}
if (c=='.'){ if (flag == 1) return 0; flag=1;}
++i;
}
val = val*pow(10,j);
return val;
}
Change all your floats to doubles. When I tested it, that gave the same result as the library function atof for your test case.
atof returns double, not float. Remember that it actually is double and not float that is the "normal" floating-point type in C. A floating-point literal, such as 3.14, is of type double, and library functions such as sin, log and (the perhaps deceptively named) atof work with doubles.
It will still not be "precise", though. The closest you can get to 1236.965 as a float is (exactly) 1236.9649658203125, and as a double 1236.964999999999918145476840436458587646484375, which will be rounded to 1236.965000 by printf. No matter how many bits you have in a binary floating-point number, 1236.965 can't be exactly represented, similar to how 1/3 can't be exactly represented with a finite number of decimal digits: 0.3333333333333333...
And also, as seen in the discussion in comments, this is a hard problem, with many possible pitfalls if you want code that will always give the closest value.
I used your code as inspiration to write my own.
What other commenters and answers do not recognize is that the original reason for the question is an embedded situation. In my case the library "atof" pulls in something that does "printf" which pulls in "systemcalls" which I don't have.
So.... here I present a simple (does not implement exponential notation) atof implementation that works in floats, and is suitable for embedding.
My implementation uses way less variables.
float ratof(char *arr)
{
float val = 0;
int afterdot=0;
float scale=1;
int neg = 0;
if (*arr == '-') {
arr++;
neg = 1;
}
while (*arr) {
if (afterdot) {
scale = scale/10;
val = val + (*arr-'0')*scale;
} else {
if (*arr == '.')
afterdot++;
else
val = val * 10.0 + (*arr - '0');
}
arr++;
}
if(neg) return -val;
else return val;
}
how to make the user defined atof() implementation more 'correct' ?
Easy: 1) never overflow intermediate calculation and 2) only round once (at the end).
It is hard to do those 2 steps.
Note: C's atof(), strtof(), etc. also handle exponential notation - in decimal and hex.
Potential roundings
val*10
(val*10)+(c-'0');
pow(10,j)
val*pow(10,j) // This last multiplication is the only tolerable one.
Potential overflow (even though the final answer is within range)
val*10
(val*10)+(c-'0');
pow(10,j)
Using a wider type like double can greatly lessen the occurrence of such problems and achieve OP's "more 'correct'". Yet they still exist.
This is not an easy problem to solved to get the best (correct) floating point result from all string inputs.
Sample approaches to solve.
Avoid overflow: rather than pow(10,j):
val = val*pow(5,j); // rounds, `pow(5,j)` not expected to overflow a finite final result.
val = val*pow(2,j); // Does not round except at extremes
Code should form (ival*10)+(c-'0') using extended integer math in the loop for exactness.
Yet this is just scratching the surface of the many corner cases.
#Eric Postpischil commented on a robust C++ code that handles non-exponential notation string input well. It does initial math using integers and only rounds later in the process. This linked code is not visible unless your rep is 10,000+ as the question was deleted.
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
int main()
{
int i,a,n,r;
n=12345;
r=0;
for(i=4;i>=0;i--)
{
a=n%10;
n=n/10;
r=r+a*pow(10,i);
}
printf("%d",r);
return 0;
}
Current output - 54320
Expected output - 54321
Please advise on what I may change in my code to reflect the correct output.
The pow function returns a value of type double. Because this is a floating point type, the result it returns will not always be exact.
What's happening in this case is that on the last iteration of the loop pow(10, 0) returns a value slightly less than 1. This results in the right hand side of r=r+a*pow(10,i); to similarly be slightly less than 54321. When this value is then assigned to r, which is of type int, it gets truncated.
Rather than using the pow function here, use the following:
r=r*10+a;
This shifts the current digits in r over by 1, then adds the newest digit to the end. Also, rather than using a for loop, use while (n>0) instead. Then it doesn't matter how many digits you have.
while (n>0)
{
a=n%10;
n=n/10;
r=r*10+a;
}
Here is a simplified version of your algorithm:
void reverse_digits(int a) {
int b = 0;
while (a > 0) {
b = b * 10 + a % 10;
a /= 10;
}
printf("%d\n", b);
}
As for converting to character arrays as mentioned in the comments it's worth to notice that the convertion function will do similar arithmetic operations in order to convert the integer to character array, so doing the reversing using integers seems more convenient.
I am trying to convert decimal number to binary number using recursion.
But I am getting wrong output...I tried to debug the program and got stuck with "pow()".
I inserted many printf statements to see the status of the variables...
Here is my program...
#include<stdio.h>
#include<conio.h>
#include<math.h>
void main(){
int n,k;
int z;
long b,j;
long binary(int,int);
printf("Enter a Number : ");
scanf("%d",&n);
printf("Binary Equivalent is : ");
k=log2(n);
b=binary(n,k);
z=pow(10,k);
printf("\n\nb=%d ,z=%d",b,z);
}
long binary(int n,int c)
{
int a,np;
static long b=0;
if(n<=1){
b=(n%2)*(int)pow(10,c)+b;
printf("\n nmod2=%d\nb=%ld\nc=%d\nn=%d ",(n%2),b,c,n);
return b;
}
else{
a=n%2;
np=pow(10,c);
b=a*np+b;
printf("\n a=%d,np=%d \n nmod2=%d \n b=%ld \n c=%d \n n=%d ",a,np,(n%2),b,c,n);
binary(n/2,--c);
}
}
Output is:
Enter a Number : 5
Binary Equivalent is :
a=1,np=99
nmod2=1
b=99
c=2
n=5
a=0,np=10
nmod2=0
b=99
c=1
n=2
nmod2=1
b=100
c=0
n=1
b=100 ,z=100
why the "pow(10,c)" in binary() when c=2 equals 99 why not 100 as in main()?
The problem is here:
(int)pow(10,c)
The result is around 100, but rounding it down with (int) can get you either 99 or 100 depending on the roundoff error of pow.
This is a handy function lround in math.h that should help you. It rounds a number towards the closest integer, rounding 0.5 towards zero.
Alternatively, you could define:
int my_round(double f) {
return (int)(f+0.5);
}
Adding 0.5 and rounding down looks like rounding to the closest integer.
The pow() function is a floating-point function, which tends to screw up such stuff. You shouldn't use it for integers without proper rounding to compensate.
Multiple problems.
As others have point out that the result of pow(10,c) is the problem. A good pow() would return exactly 100.0 for pow(10,2). It is reasonable to expect that behavior from pow(), but a cautious programmer would do as others suggest and round-to-nearest a floating point number to an int.
Round to nearest is best handle with a library function. Should one want to roll your own:
int IRound(double f) { return (f > 0.0) ? (int)(f + 0.5) : (int)(f - 0.5); }
long binary(int n,int c) does not return a value when n > 1. Suspect return binary(n/2,--c) is wanted.
The static long b=0; is a bad way to deal with recursion. long binary(int n,int c) would nominally correctly run only once. A second call, b would not necessarily start at 0.
Given pow() is flaky, log2() may need special care too.
I want to write a program to see if an integer is the power of another integer(true return 1 and false return 0). And the code is as follows:
#include <stdio.h>
#include <math.h>
int cal_base_power(int);
int main()
{
int x,r;
printf("Please input an integer\n");
scanf("%d\n",&x);
r=cal_base_power(x);
printf("result is %d\n",r);
}
int cal_base_power(int input)
{
int i=2;
double a=pow(input,(double)1/i);
while (a>=2)
{
if ((double)a==(int)a)
return 1;
i++;
a=pow(input,(double)1/i);
}
return 0;
}
It is ok with 4,8,125 some cases like these. But failed when input 216 and 343. Also it will not automatically output 0 and 1. I must input some random characteristics before the result 0 or 1 comes out.
Can anyone help me? I know it is quite easy. But I really need your help
You can't do equality comparisons on floating-point.
(double)a==(int)a
Due to round-off error, a might not be exactly an integer even though it's supposed to be.
EDIT:
There's two ways to do this:
Allow tolerance on the comparison: fabs(a - (int)a) < 0.0001 (or something like that, you'll need to tweak the threshold.)
Round a to the nearest integer and power it back up (using integers only) to see if it matches the input.
I made a program to find if a number belongs to fibonacci series or not and if it does whats its position.Whenever i type a number the if Condition goes wrong.
#include<stdio.h>
#include<conio.h>
#include<math.h>
void main(void)
{
int i,x=1,y=1,z,num;
clrscr();
printf("Enter a number to find in fibonacci series:");
scanf("%d",&num);
/*to find if the number is a part of fibonacci series or not*/
if((isdigit(sqrt(5*num*num+4)))||(isdigit(sqrt(5*num*num-4)))) //<-- this if!
{//belongs to fibo!
for(i=1; ;i++)
{
if(x==num)
break;
z=x+y;
x=y;
y=z;
}
printf("%d is the %d term of fibonacci series.",num,i);
}
else
printf("Dear user,The entered number is not a part of the fibonacci series.");
getch();
}
You're misunderstanding the isDigit function.
isDigit takes an ASCII character code and returns true if it represents a decimal digit.
You want to check whether the double returned by sqrt is an integer.
There's an obvious error in your use of isdigit(). That function (usually macro) is used to tell if a character is one of the characters 0..9 - certainly your code is dealing with numbers consistently and there's no need for character checking.
You'll want to take a closer look at what you're trying to accomplish. You're welcome to ask us which C functions might be suitable.
EDIT:
Ah, you want to know if that funky expression is an integer value. Alas, there's no built-in function for that. I haven't tested this, but I'd write
double a = (funky expr);
if (a == rint(a)) ...
... where rint() is a function that returns the double that's the nearest integer value to the given argument.
Why are you using isdigit? The result of sqrt is a double - you need to check that value directly.
You want to check if 5 * num * num + 4 or 5 * num * num - 4 is a perfect square. A function that will do this is:
int is_perfect_sq(double d)
{
double sqroot = rint(sqrt(d));
return (sqroot * sqroot) == d;
}
Note - this is a good disproof of the notion that you should never compare floating point numbers for equality. In this case, it is fine, since a "perfect square" must be an integer.