I'm trying to make a logarithm calculator and got stuck—it doesn't print out a value. The problem may be at lines 15 or 24 or both. How can I make it print the value (all written in C).
Here's the full code:
#include <stdio.h>
#include <stdlib.h>
// Finds base 10 logarithms
int main()
{
float result;
float base = 10.0;
float multiplier = 1.0;
// float counter1 = 0.0;
// float counter2 = 0;
printf("Input result: ");
scanf("%l", result);
// Solves for all results above the base
if(result > base) {
while(result > multiplier) {
multiplier = multiplier * multiplier; // the multiplier has to check non-whole numbers
multiplier += 0.001;
} // division
}
printf("Your exponent is: %l \n", &multiplier);
printf("Hello mathematics!");
return 0;
}
All help appreciated,
Xebiq
you should delete & in printf,and add & in scanf.
printf("Your exponent is: %f \n", multiplier);
scanf("%f", &result);
and use %f in them.
and with base 10 I suggest this function to calculate log:
unsigned int Log2n(unsigned int n)
{
return (n > 1) ? 1 + Log2n(n / 10) : 0;
}
also you should know about Floating-point numbers here:
multiplier += 0.001;
probably exactly 0.001 won't be added to multiplier when I debugged this 0.00100005 was being add to multiplier in my compiler.(which will affect multiplying)
In printf remove '&' and in scanf add '&' before variable.
Related
Here is my code:
#include <stdio.h>
#include <math.h>
int main() {
int num, i = 0, new_num = 0, u;
printf("Enter a number: ");
scanf("%d", &num);
while (num > 0) {
u = num % 10;
if (u % 2 == 0)
u = u;
if (u % 2 == 1)
u = u - 1;
new_num = new_num + u * pow(10, i);
num = num / 10;
i++;
}
printf("The new number is: %d", new_num);
return 0;
}
Now, when I am doing this in gcc(VS Code), for 2-digit number everything is ok. But for digits more than three I am getting a error. Like Input=23145 Output=22043. But I was expecting output=22044.
Also, if I run the same code in DevC/C++, there is no error.
Can anyone help me out in this?
Your program produces the expected output on my system: 22044 for 23145, but this might depend on the implementation of the pow function.
The reason you get a different output is probably a side effect of a precision issue with the pow() function in your C library: if pow(x, y) is implemented as exp(y * log(x)), the result for integral values of x and y could be very close but inferior to the actual integral value, causing the conversion to int to produce the previous integer. Some C library authors make a special case of integral arguments to avoid this problem, but it is highly recommended to avoid floating point functions for integer arithmetics to prevent such tricky issues.
I would advise some more changes in your code:
test the return value of scanf().
remove the if (u % 2 == 0) u = u; part, it has no effect.
in any case, there should be an else clause to not use the result of the previous case when testing for odd digits.
do not use the floating point function pow(): just keep a multiplier variable and update it in the loop.
the program does not handle negative numbers.
Here is a modified version:
#include <stdio.h>
int main() {
int num, new_num = 0, pow10 = 1;
printf("Enter a number: ");
if (scanf("%d", &num) != 1)
return 1;
while (num != 0) {
int digit = num % 10;
/* decrement odd digits absolute value */
digit -= digit % 2;
new_num = new_num + digit * pow10;
pow10 = pow10 * 10;
num = num / 10;
}
printf("The new number is: %d\n", new_num);
return 0;
}
Note that digit -= digit % 2; will decrement positive odd digits and actually increment negative odd digits, which effectively always decrements the absolute value of odd digits. This way both positive values and negative values are handled correctly.
In my instance of Visual Studio Code, for an input 23145, I indeed find 22044 as an output.
I guess the divergence comes with the cast of pow(10,i). Pow function in C returns a double which is not what you really want here. I strongly advice to not use the pow function for integer arithmetic.
A solution could be :
uint16_t i = 0u;
uint16_t current_digit = 0u, decimal_digit = 1u;
uint16_t new_number = 0u;
uint16_t number = 23145u;
while(number > 0u) {
current_digit = number % 10;
if (current_digit % 2) {
current_digit = current_digit - 1;
}
new_number = new_number + current_digit * decimal_digit;
decimal_digit *= 10u;
number /= 10;
i++;
}
printf("The new number is: %d", new_number);
It seems that the problem is using the function pow that returns a double value.
If you are dealing with integers then it is better to avoid using functions that return doubles due to a possible truncation then a double is converted to an integer.
Also pay attention to that the user can enter a negative number. Your program allows to do that. In this case your program also will produce an incorrect result.
I would write the program the following way
#include <stdio.h>
int main( void )
{
while (1)
{
const int Base = 10;
int num;
printf( "Enter a number (0 - exit): " );
if (scanf( "%d", &num ) != 1 || num == 0) break;
int new_num = 0;
for (int tmp = num, multiplier = 1; tmp != 0; tmp /= Base)
{
int digit = tmp % Base;
if (digit % 2 != 0)
{
digit += ( digit < 0 ? 1 : -1 );
}
new_num = new_num + multiplier * digit;
multiplier *= Base;
}
printf( "The original number is %d and the new number is: %d\n",
num, new_num );
putchar( '\n' );
}
}
The program output is
Enter a number (0 - exit): -123456789
The original number is -123456789 and the new number is: -22446688
Enter a number (0 - exit): 123456789
The original number is 123456789 and the new number is: 22446688
Enter a number (0 - exit): 0
If even for negative digits to add -1 then you should substitute this if statement
if (digit % 2 != 0)
{
digit += ( digit < 0 ? 1 : -1 );
}
for this one
if (digit % 2 != 0)
{
digit = ( digit -1 ) % Base;
}
In this case the program output might look like
Enter a number (0 - exit): -123456789
The original number is -123456789 and the new number is: -224466880
Enter a number (0 - exit): 123456789
The original number is 123456789 and the new number is: 22446688
Enter a number (0 - exit): 0
That is in this case the new value for the negative value -123456789 will be -224466880.
#include<stdio.h>
float abso(float a)
{
if(a<0.0)
return(-1*a);
else
return a;
}
int sqert(int x)
{
float x1 = (float)x;
float g1, g2;
g1 = x1/2.0;
g2 = x1/g1;
double e=0.000000001;
int sr;
while(abso(g1-g2)>=e)
{
g2 = (g1+x1/g1)/2.0;
g1 = x1/g2;
}
sr = (int)g1;
return(sr);
}
int main()
{
int num;
//num = 0;
printf("Enter a num between 1 and 1000 ");
scanf("%d",&num);
//printf("hello");
int flag;
flag = 0;
int i;
i = 2;
int m, j;
m = j = 0;
while(i<=num)
{
flag = 1;
if(i==2)
{
printf("%d ",i);
i++;
}
else if(i==3)
{
printf("%d ",i);
i= i+2;
}
else if(i>3)
{
m = sqert(i);
for(j=2;j<=m;j++)
{
if((i%j) == 0)
{
flag = 0;
break;
}
}
if(flag == 0)
{
i = i + 2;
continue;
}
if(j==m+1)
printf("%d ",i);
i = i + 2;
}
}
printf("\n");
return(0);
}
Here sqert function is taking square root of the input value and abso function is taking the absoulte value of given value.
The logic used is simple we are iterating to the square root of that number and then check for every number if it is divisible by any other number than itself then it is not a prime number else it is a prime number.
But this program is working only for value upto 5. After that it is not printing anything. It is not printing the entered number also.
Any help would be appreciated.
In your code, you are trying to compare float with double.
while(abso(g1-g2)>=e)
This is not correct because of the difference in precision between float and double.
double has 2 times more precision than float.
float is a 32 bit IEEE 754 single precision floating point number
(1 bit for the sign, 8 bits for the exponent, and 23* for the value),
i.e. float has 7 decimal digits of precision.
double is a 64 bit IEEE 754 double precision floating point number
(1 bit for the sign, 11 bits for the exponent, and 52* bits for the value),
i.e. double has 15 decimal digits of precision.
Declare e as float and make sure it is assigned a value that fits with the precision of float.
Something like:
float e = 0.00001;
Then your code will work as intended.
#EricPostpischil in the comments said that the sqert function may not always return the correct approximation. This is correct.
So it is better to use sqrt from math.h which works perfectly instead of sqert.
Sorry I feel stupid asking this and am prepared to lose half of my points asking this but why does this algorithm not work? It works up to a point. After the number 13 the factorials are a little off. For instance the numbers do not entirely match in the hundreds thousands place and onward.
#include <stdio.h>
float factorial(unsigned int i) {
if (i <= 1) {
return 1;
}
return i * factorial(i - 1);
}
int main() {
int i = 13;
printf("Factorial of %d is %f\n", i, factorial(i));
return 0;
}
Here's the output:
Factorial of 13 is 6227020800.000000
Here is an example of inaccurate output:
Factorial of 14 is 87178289152.000000
The output for the number 14 should actually be this (from mathisfun.com)
14 87,178,291,200
I changed the return type to float to obtain more accurate output but I obtained this code for the most part from here: https://www.tutorialspoint.com/cprogramming/c_recursion.htm
EDIT: If I change to the return type to double the output is accurate up to 21.I am using the %Lf string formatter for the output in the printf function.
Simple. float cannot accurately store integers above 16777216 without loss of precision.
int is better than float. But try long long so you can properly store 19 digits.
OP is encountering the precision limits of float. For typical float, whole number values above 16777216.0f are not all exactly representable. Some factorial results above this point are exactly representable.
Let us try this with different types.
At 11!, the float results exceeds 16777216.0f and is exactly correct.
At 14!, the float result is imprecise because of limited precision.
At 23!, the double result is imprecise because of limited precision.
At 22!, the answer exceeds my uintmax_t range. (64-bit)
At 35!, the answer exceeds my float range.
At 171!, the answer exceeds my double range.
A string representation is accurate endlessly until it reaches buffer limitations.
#include <stdint.h>
#include <string.h>
#include <stdio.h>
uintmax_t factorial_uintmax(unsigned int i) {
if (i <= 1) {
return 1;
}
return i * factorial_uintmax(i - 1);
}
float factorial_float(unsigned int i) {
if (i <= 1) {
return 1;
}
return i * factorial_float(i - 1);
}
double factorial_double(unsigned int i) {
if (i <= 1) {
return 1;
}
return i * factorial_double(i - 1);
}
char * string_mult(char *y, unsigned base, unsigned x) {
size_t len = strlen(y);
unsigned acc = 0;
size_t i = len;
while (i > 0) {
i--;
acc += (y[i] - '0') * x;
y[i] = acc % base + '0';
acc /= base;
}
while (acc) {
memmove(&y[1], &y[0], ++len);
y[0] = acc % base + '0';
acc /= base;
}
return y;
}
char *factorial_string(char *dest, unsigned int i) {
strcpy(dest, "1");
for (unsigned m = 2; m <= i; m++) {
string_mult(dest, 10, m);
}
return dest;
}
void factorial_test(unsigned int i) {
uintmax_t u = factorial_uintmax(i);
float f = factorial_float(i);
double d = factorial_double(i);
char s[2000];
factorial_string(s, i);
printf("factorial of %3d is uintmax_t: %ju\n", i, u);
printf(" float: %.0f %s\n", f, "*" + (1.0 * f == u));
printf(" double: %.0f %s\n", d, "*" + (d == u));
printf(" string: %s\n", s);
}
int main(void) {
for (unsigned i = 11; i < 172; i++)
factorial_test(i);
return 0;
}
Output
factorial of 11 is uintmax_t: 39916800
float: 39916800
double: 39916800
string: 39916800
factorial of 12 is uintmax_t: 479001600
float: 479001600
double: 479001600
string: 479001600
factorial of 13 is uintmax_t: 6227020800
float: 6227020800
double: 6227020800
string: 6227020800
factorial of 14 is uintmax_t: 87178291200
float: 87178289152 *
double: 87178291200
string: 87178291200
factorial of 20 is uintmax_t: 2432902008176640000
float: 2432902023163674624 *
double: 2432902008176640000
string: 2432902008176640000
factorial of 21 is uintmax_t: 14197454024290336768
float: 51090940837169725440 *
double: 51090942171709440000 *
string: 51090942171709440000
factorial of 22 is uintmax_t: 17196083355034583040
float: 1124000724806013026304 *
double: 1124000727777607680000 *
string: 1124000727777607680000
factorial of 23 is uintmax_t: 8128291617894825984
float: 25852017444594485559296 *
double: 25852016738884978212864 *
string: 25852016738884976640000
factorial of 34 is uintmax_t: 4926277576697053184
float: 295232822996533287161359432338880069632 *
double: 295232799039604119555149671006000381952 *
string: 295232799039604140847618609643520000000
factorial of 35 is uintmax_t: 6399018521010896896
float: inf *
double: 10333147966386144222209170348167175077888 *
string: 10333147966386144929666651337523200000000
factorial of 170 is uintmax_t: 0
float: inf *
double: 72574156153079940453996357155895914678961840000000... *
string: 72574156153079989673967282111292631147169916812964...
factorial of 171 is uintmax_t: 0
float: inf *
double: inf *
string: 12410180702176678234248405241031039926166055775016...
Someone posted a similar question a while back. The consensus was if you're writing it for work use a big number library (like GMP) and if it's a programming exercise write up a solution using a character array.
For example:
/* fact50.c
calculate a table of factorials from 0! to 50! by keeping a running sum of character digits
*/
#include <stdio.h>
#include <string.h>
int main (void)
{
printf ("\n Table of Factorials\n\n");
// length of arrays = 65 character digits
char str[] =
"00000000000000000000000000000000000000000000000000000000000000000";
char sum[] =
"00000000000000000000000000000000000000000000000000000000000000001";
const int len = strlen (str);
int index;
for ( int i = 0; i <= 50; ++i ) {
memcpy (str, sum, len);
for ( int j = 1; j <= i - 1; ++j ) {
index = len - 1;
int carry = 0;
do {
int digit = (sum[index] - '0') + (str[index] - '0') + carry;
carry = 0;
if ( digit > 9 ) {
carry = 1;
digit %= 10;
}
sum[index] = digit + '0';
--index;
}
while ( index >= 0 );
}
printf ("%2i! = ", i);
for ( index = 0; sum[index] == '0'; ++index )
printf ("%c", '.');
for ( ; index < len; ++index )
printf ("%c", sum[index]);
printf ("\n");
}
return 0;
}
Why Is This Factorial Algorithm Not Accurate
There's nothing wrong in your algorithm as such. It is just that the data types you use have a limit for the highest number they can store. This will be a problem no matter which algorithm you choose. You can change the data types from float to something like long double to hold something bigger. But eventually it will still start failing once the factorial value exceeds the capacity of that data type. In my opinion, you should put an a condition in your factorial function to return without calculating anything if the passed in argument is greater than a value that your chosen datatype can support.
float can represent a wider range of numbers than int, but it cannot represent all the values within that range - as you approach the edge of the range (i.e., as the magnitudes of the values increase), the gap between representable values gets wider.
For example, if you cannot represent values between 0.123 and 0.124, then you also cannot represent values between 123.0 and 124.0, or 1230.0 and 1240.0, or 12300.0 and 12400.0, etc. (of course, IEEE-754 single-precision float gives you a bit more precision than that).
Having said that, float should be able to represent all integer values up to 224 exactly, so I'm going to bet the issue is in the printf call - float parameters are "promoted" to double, so there's a representation change involved, and that may account for the lost precision.
Try changing the return type of factorial to double and see if that doesn't help.
<gratuitous rant>
Every time I see a recursive factorial function I want to scream. Recursion in this particular case offers no improvement in either code clarity or performance over an iterative solution:
double fac( int x )
{
double result = 1.0;
while ( x )
{
result *= x--;
}
return result;
}
and can in fact result in worse performance due to the overhead of so many function calls.
Yes, the definition of a factorial is recursive, but the implementation of a factorial function doesn't have to be. Same for Fibonacci sequences. There's even a closed form solution for Fibonacci numbers
Fn = ((1 + √5)n - (1 - √5)n) / (2n * √5)
that doesn't require any looping in the first place.
Recursion's great for algorithms that partition their data into relatively few, equal-sized subsets (Quicksort, tree traversals, etc.). For something like this, where the partitioning is N-1 subsets of 1 element? Not so much.
</gratuitous rant>
I'm trying to calculate the decimal amount in float but it won't calculate if the input is "0.01". However, it will calculate if the input is "0.02" but with wrong calculation. Here is the code:
#include <stdio.h>
#include <cs50.h>
float MCounting = 0.00;
int MAmountCoin = 0;
float MAmountUsed = 0.00;
int MCoinCount = 0;
float MRemainAmount = 0;
int MCoinOut = 0;
int MTotCoinOut = 0;
int main(void)
{
float Amount;
float MRemainAmount;
do
{
printf("Specify the amount you want in change: ");
Amount = GetFloat();
MRemainAmount = Amount;
}
while (Amount < 0 );
if (MRemainAmount > 0 || MRemainAmount < .05 )
printf ("\n\n ***** Calculatin for 0.01 *****\n");
{
printf ("MRemainAmount Before calculation: %.2f\n",MRemainAmount);
MCoinOut = MRemainAmount / .01;
printf ("MCoinOut = %i...MTotCoinOut = %i\n",MCoinOut,MTotCoinOut);
MRemainAmount = MRemainAmount - (MCoinOut * .01);
printf ("MRemainAmount = %.2f\n",MRemainAmount);
MTotCoinOut = MCoinOut + MTotCoinOut;
printf ("MTotCoinOut = %i\n",MTotCoinOut);
}
{ printf("Total Coin Out%i\n",MTotCoinOut); }
}
What's going wrong and how can I fix it?
You are hitting your epsilon limit. Since you are using floats you are limited in representation by FLT_EPSILON; if you were using a double, you would see improved resolution of DBL_EPSILON. (These values are from <float.h>)
#define DBL_EPSILON 2.2204460492503131e-016 /* smallest such that 1.0+DBL_EPSILON != 1.0 */
#define FLT_EPSILON 1.192092896e-07F /* smallest such that 1.0+FLT_EPSILON != 1.0 */
Thus if you are using a value like 10000, roughly, you're smallest change in value is something in the vicinity of 10000 * FLT_EPSILON, which would be about .012. If you want to represent with better precision, use doubles.
It is due to the imprecise representation of floating point numbers in the computers memory.
Read up on http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
Ok so here's what i have so far:
#include <stdio.h>
#include <math.h>
//#define PI 3.14159
int factorial(int n){
if(n <= 1)
return(1);
else
return(n * factorial(n-1));
}
void McLaurin(float pi){
int factorial(int);
float x = 42*pi/180;
int i, val=0, sign;
for(i=1, sign=-1; i<11; i+=2){
sign *= -1; // alternate sign of cos(0) which is 1
val += (sign*(pow(x, i)) / factorial(i));
}
printf("\nMcLaurin of 42 = %d\n", val);
}
void Taylor(float pi){
int factorial(int);
float x;
int i;
float val=0.00, sign;
float a = pi/3;
printf("Enter x in degrees:\n");
scanf("%f", &x);
x=x*pi/180.0;
printf("%f",x);
for(i=0, sign=-1.0; i<2; i++){
if(i%2==1)
sign *= -1.0; // alternate sign of cos(0) which is 1
printf("%f",sign);
if(i%2==1)
val += (sign*sin(a)*(pow(x-a, i)) / factorial(i));
else
val += (sign*cos(a)*(pow(x-a, i)) / factorial(i));
printf("%d",factorial(i));
}
printf("\nTaylor of sin(%g degrees) = %d\n", (x*180.0)/pi, val);
}
main(){
float pi=3.14159;
void McLaurin(float);
void Taylor(float);
McLaurin(pi);
Taylor(pi);
}
and here's the output:
McLaurin of 42 = 0
Enter x in degrees:
42
0.733038-1.00000011.0000001
Taylor of sin(42 degrees) = -1073741824
I suspect the reason for these outrageous numbers goes with the fact that I mixed up my floats and ints? But i just cant figure it out...!! Maybe its a math thing, but its never been a strength of mine let alone program with calculus. Also the Mclaurin fails, how does it equal zero? WTF! Please help correct my noobish code. I am still a beginner...
----Update----
#include <stdio.h>
#include <math.h>
//#define PI 3.14159
int factorial(int n){
if(n <= 1)
return(1);
else
return(n * factorial(n-1));
}
void McLaurin(float pi){
int factorial(int);
float x = 42*pi/180, val=0;
int i, sign;
for(i=1, sign=-1; i<11; i+=2){
sign *= -1; // alternate sign of cos(0) which is 1
val += (sign*(pow(x, i)) / factorial(i));
}
printf("\nMcLaurin of of sin(%f degrees) = %f\n", (x*180.0)/pi, val);
}
void Taylor(float pi){
int factorial(int);
float x;
int i;
float val=0, sign;
float a = pi/3;
printf("Enter x in degrees:\n");
scanf("%f", &x);
x=x*pi/180.0;
printf("%f",x);
for(i=0, sign=-1.0; i<2; i++){
if(i%2==0)
sign *= -1; // alternate sign of cos(0) which is 1
printf("%f",sign);
if(i%2==0)
val += (sign*sin(a)*(pow(x-a, i)) / factorial(i));
else
val += (sign*cos(a)*(pow(x-a, i)) / factorial(i));
printf("%d",factorial(i));
}
printf("\nTaylor of sin(%f degrees) = %f\n", (x*180.0)/pi, val);
}
main(){
float pi=3.14159;
void McLaurin(float);
void Taylor(float);
McLaurin(pi);
Taylor(pi);
}
Gives me weird error.
/usr/lib/gcc/i686-pc-cygwin/3.4.4/../../../../i686-pc-cygwin/bin/ld: cannot open output file a.exe: Device or resource busy
collect2: ld returned 1 exit status
Can anyone explain what's wrong now?
Some potential sources of error:
your value of pi doesn't have sufficient digits for even float accuracy;
in your function Maclaurin you have val as an integer, on which you perform division;
in Taylor you only use 2 terms in the series
I think ?
a few things jump out:
in McLauren you define val (your calculated value) as an int. try defining it as a float
in Taylor you are only flipping your sign every other time so it goes -1, 1, -1, -1, 1, 1 .... and so on
i think your formula for the Taylor series is incorrect, after refreshing myself on wikipedia, you shouldn't be calling sin or cos (because that's what you are trying to calculate)
good luck!
This one that have already been mentioned is definitely troublesome:
val should be a float in McLaurin()
In addition, you need to use %f or %g instead of %d when using printf() to print out your vals. That's ultimately why you're getting such crazy numbers: floats being interpreted as ints.
Also, in Taylor(), you need to change your two if statements to be
if(i%2==0)
because you are Taylor expanding sin, not cos.
Doing these things yields 0.669130 and 0.708945 for the MacLaurin and Taylor series answers, respectively, using the same number of terms as in your code. If I add two more terms to the Taylor series answer (use i<4 instead of i<2), I get 0.668793. The true answer (using the same pi as you used) is 0.669130 which the Taylor series answer gets to with 3 more additional terms added in.