C, logs, binary, and the number four. they don't mix - c

#include <stdio.h>
#include <math.h>
/* converts to binary using logs */
int main()
{
long int decimalNUM = 0, binaryNUM = 0, exponentNUM = 0;
printf("Enter a number to be converted to binary.\t");
scanf("%ld", &decimalNUM);
fflush(stdin);
int origDEC = decimalNUM;
while (decimalNUM > 0)
{
exponentNUM = (log(decimalNUM))/(log(2));
binaryNUM += pow(10, exponentNUM);
decimalNUM -= pow(2, exponentNUM);
}
printf("\nBINARY FORM OF %ld is %ld", origDEC, binaryNUM);
getchar();
return binaryNUM;
}
If STDIN is 4 it returns 99 and it should not. On IDEONE it returns 100. Why?
EDIT seems that any even number above two returns something with nines in it

Floating point operations like log are not exact. On my machine this code runs as expected (4 on STDIN gives 100).
One way you could do this, is by using the mod (%) operator with successive powers of two.

Works fine : http://ideone.com/PPZG5
As mentioned in the comments, your approach is really strange.
A general base-n conversion routine looks like:
void print_base_n(int val, int n) {
if(val==0) { printf("0"); return; }
else if(val < n) { printf("%d", val); return; }
print_base_n(val/n, n);
printf("%d", val % n);
}

Related

find sum of digits after decimal point

I want to find the sum of all the digits entered by a user after the decimal point in c.
Eg. 12.36 must return 9
15.06 must return 6
9.0 must return 0
My approach
#include <stdio.h>
int main()
{
double num,numfloat;
int digitf,numint,sumf=0;
scanf("%lf",&num);
numint=num;
numfloat=num-numint;
while(numfloat!=0)
{
digitf=(numfloat*10);
numfloat=numfloat*10-digitf;
sumf=sumf+digitf;
}
printf("Sum float %d",sumf);
return 0;
}
The sum comes out a lot more than the expected.
Try, (The reason why in this example, I haven't joined the loops is that: I want this to be usable on other situations where they use an alternate method of validating input, see the SECOND EXAMPLE for both loops joined):
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main() {
// read from stdin
char num[512] = { };
fgets(num, sizeof(num), stdin);
num[strcspn(num, "\n")] = '\0';
// verify if number is valid
int decimal_point_found = 0;
for (int i = 0; i < strlen(num); i++) {
// check if digit
if (!isdigit(num[i])) {
// be safe from multiple decimal points
if (num[i] == '.' && decimal_point_found == 0) {
decimal_point_found = 1;
continue;
}
printf("ERROR: enter a valid number\n");
return 1;
}
}
int total = 0;
// add all the decimal points
for (int i = 0, decimal_point_found = 0; i < strlen(num); i++) {
if (decimal_point_found == 1) {
total += num[i] - '0'; // - '0' converts char to int
}
if (num[i] == '.') {
decimal_point_found = 1;
}
}
// show total
printf("%d\n", total);
}
In the above, I have read char instead of reading float. I have read using fgets() which is safer than scanf().
Handling char makes it so much easier to calculate such things. As we know the number of digits, etc.
With both loops joined:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main() {
char num[512] = { };
fgets(num, 512, stdin);
num[strcspn(num, "\n")] = '\0';
// verify if number is valid
int decimal_point_found = 0;
int total = 0;
for (int i = 0; i < strlen(num); i++) {
if (!isdigit(num[i])) {
if (num[i] == '.' && decimal_point_found == 0) {
decimal_point_found = 1;
continue;
}
printf("ERROR: enter a valid number\n");
break;
}
if (decimal_point_found == 1) {
total += num[i] - '0';
}
}
printf("%d\n", total);
}
Original code fails as unless the fraction if exactly an integer/power-of-2, the input number, as decimal text, does not convert exactly to the same double. Instead num is the closet double possible. Yet that closest double may have many more digits when manipulated.
Further OP's numfloat=numfloat*10-digitf; injects repeated rounding errors.
Instead code needs to compensate for that rounding in some fashion.
the input has to be a number
Hmm, better to read in as a string, yet we can code a tolerable solution if we know the length of input by using "%n" to record the length of user input.
width below is the number of non-white-space characters in input. If we assume things like 1) sign only when negative, 2) no exponential 3) not infinity nor NAN, 4) no more than 15 significant digits 5) no more than 15 fraction digits --> then width will almost always*1 gives us what is needed to process num.
#include<stdio.h>
#include<math.h>
int sumFraction(void) {
int sum = 0;
double num;
int start, end;
if (scanf(" %n%lf%n", &start, &num, &end) != 1) {
return -1;
}
if (num == 0) {
return 0;
}
int width = end - start;
if (num < 0) {
num = -num;
width--;
}
int p10 = (int) log10(num);
width--; // Decrement for the '.'
if (width > 15) {
printf("Too many leading digits\n");
return -1;
}
width -= (p10 + 1);
// Only care about fractional part
double ipart;
num = modf(num, &ipart);
if (num == 0) {
return 0;
}
// assert(width >= 0);
num *= pow(10, width);
long long ival = llround(num); // Form an integer
while (width > 0) {
width--;
sum += ival % 10;
ival /= 10;
}
return sum;
}
int main() {
printf(" %d\n", sumFraction());
printf(" %d\n", sumFraction());
printf(" %d\n", sumFraction());
}
*1 IMO, code is not robust as the given limitation of not reading in as a string is not real for the real world. So here is a non-real solution.
You mentioned in a comment that the input has to be a number.
This first point to mention is that when coding, we are not manipulating such abstract things as numbers,
but imperfection representations of numbers. Think to the famous painting "This is not a pipe".
Same here, "This is not a number".
float, double and char* are all or can be all representations of numbers.
Depending on the context, one representation can be more suitable than others. Here, using a char* is the best solution, has no internal conversion error occurs.
Now, let us assume that the input format double is imposed by your professor.
Why is your code not working? Mainly because internally, the representation of the numbers is generally imperfect.
A small error can lead to a large error when converting a float to an integer.
For example, int i = 0.999999 will give i = 0.
The solution is to account for the internal error representation, by introducing a margin, e.g. eps = 1.0e-14,
when performing the float-to-integer conversion, or when testing if a number is equal to 0.
A difficulty is that the internal error is multiplied by 10 when the number is multiplied by 10. So the value of epshas to be updated accordingly.
Moreover, we have to take into accout that the mantissa provides a relative accurracy only, not an absolute one.
Therefore, the eps value must be increased when the number is large.
0.123456789 --> 45
19.1 -> 1
12.45e-36 -> 12
12345.973 -> 19
0.83 -> 11
#include <stdio.h>
int main() {
double num, numfloat;
int digitf, numint, sumf = 0;
double eps = 1.0e-14; // to deal with representation inaccuracy of numbers
if (scanf("%lf", &num) != 1) return 1;
printf("number in memory: %.20g\n", num);
if (num < 0.0) num = -num;
numint = (int) (num + eps);
numfloat = num - numint;
int deal_with_low_number = numint == 0;
while (numint) { // the mantissa only proposes a relative accurracy ...
eps *= 10;
numint /= 10;
}
while (numfloat > eps || deal_with_low_number) {
numfloat *= 10;
digitf = (int) (numfloat + eps);
numfloat -= digitf;
sumf = sumf + digitf;
if (digitf != 0) deal_with_low_number = 0;
if (!deal_with_low_number) eps *= 10;
}
printf("Sum float %d\n", sumf);
return 0;
}

Is float always rounding?

Here is my program, it turn decimal to base-"n", you can put number in "n" base what you want to turn to, it run successful but I have a question, I don't get it why the if ((float)input / (float)n <= 0) can pass in the fifth time. I'm debugging with vscode and watch the value every breakpoints and steps, here are the result
(run this line if ((float)input / (float)n <= 0))
input=20, n=2
First time : 20/2=10 (pass)
Second time : 10/2=5 (pass)
Third time : 5/2=2.5 (pass)
Forth time : 2.5/2=1 (pass) I don't understand why it is "1" not "1.25" (I think this is my main problem, is float always rouding ?)
Fifth time : 1/2=0.5 (pass)
Sixth time : 0.5/2=0 (fail and break)
Hope somebody can explain that I'll very appreciate, English not my mother tongue so forgive me.
#include <stdio.h>
#include <stdlib.h>
void rev(int num[]);
int cnt = 0;
int main()
{
int input = 20, num[10], i, n = 2;
// Decimal turn to base-n
printf("Decimal \"%d\" to base-%d = ", input, n);
for (i = 0; i < 10;)
{
if ((float)input / (float)n <= 0)
break;
else
{
num[i] = input % n;
input /= n;
i++;
cnt++;
}
}
rev(num);
printf("\n");
system("pause");
return 0;
}
void rev(int num[])
{
int i;
i = cnt - 1;
for (i; i >= 0; i--)
printf("%d", num[i]);
}
absolutely will be fail because . when you type casting float to int like int a = 3.14 ; just the decimal part will be stored exp int a = 0.5; means a equal to 0 .
When you divide input by n, you're doing integer division:
input /= n;
Integer division has an integer result. And either way, you're storing the result back to an integer, so any fractional portion is discarded.
So the values stored in input each time through the loop will be 20, 10, 5, 2 (not 2.5), 1, and 0.

Counting powers of 3 within a given range in C

I have to write a program that takes in two positive integers, start and end, where (1 < start < end). Then the program would look within this range [start, end] and count the number of powers of 3.
So, for example, if start is 2 and end is 10, the output would be 2. (as 3 and 9 are powers of 3).
Below is my code:
#include <stdio.h>
#include <math.h>
int main(void) {
int start, end, i, count = 0;
printf("Enter start and end: ");
scanf("%d %d", &start, &end);
for (i = start; i <= end; i++) {
if ((log(i) / log(3)) == floor((log(i) / log(3)))) {
printf("%d\n", i);
count++;
}
}
printf("Answer = %d\n", count);
return 0;
}
But, when I tried to run one of the test cases [3, 1000], the output is 5, when it should be 6.
3
9
27
81
729
Answer = 5
The number 243 is missing. Is there something wrong with my code?
The problem is you are using exact comparison of floating point numbers. Specifically, here:
if ((log(i)/log(3)) == floor((log(i)/log(3))))
Since log() and floor() return double, you're comparing without any tolerance two values which cannot be compared that way.
How should I do floating point comparison?
Your immediate problem has to do with the imprecision of floating point numbers, something that is generally well documented on the net, including various methods useful in fixing that problem.
However, I'm not actually going to bother referring you to them because the use of floating point is totally unnecessary here. There's a much more efficient way of doing this that involves only integers.
Rather than going through numbers in your range looking for powers of three using floating point operations, you would be better off going through powers of three (using just integer multiplication) looking for numbers in your range.
In pseudo-code, that would go something like:
powerOfThree = 1
while powerOfThree <= endRange:
if powerOfThree >= startRange:
print powerOfThree
powerOfThree = powerOfThree * 3
You could even make it more efficient by selecting a more suitable starting value for powerOfThree but, since there are only 40-odd powers of three in a 64 bit number, that's probably a waste of time.
When converting from pseudo-code to the more concrete C, you unfortunately come across the limitations of the datatypes in that language, specifically the fact that multiplication may result in overflow.
There are various ways you can avoid this this such as detecting that it's about to happen and exiting the loop early.
Given below is the function that you need, one which handles this issue, along with some test code which can be used for validating it.
#include <stdio.h>
#include <limits.h>
// I hate typing :-)
typedef unsigned long ULONG;
typedef unsigned int UINT;
static UINT countPowersOfThreeBetween (ULONG low, ULONG high) {
// Catch invalid params, just exit with zero.
if (low > high) return 0;
// Go through all powers of three.
ULONG powerOfThree = 1;
UINT count = 0;
do {
// If within your range, count it.
if ((powerOfThree >= low) && (powerOfThree <= high)) {
count++;
// printf ("DEBUG: got %lu\n", powerOfThree);
}
// Early exit if about to overflow.
if (ULONG_MAX / powerOfThree < 3) break;
// Advance to next power and continue if within range.
powerOfThree *= 3;
} while (powerOfThree <= high);
// Notify caller of count.
return count;
}
// Test function to make test suite easier.
static void testRange (ULONG low, ULONG high) {
UINT count = countPowersOfThreeBetween (low, high);
printf ("In range %lu..%lu, found %u occurrences\n", low, high, count);
}
// Test suite, add whatever you need.
int main (void) {
testRange (1000, 10);
testRange (0, 0);
testRange (9, 9);
testRange (3, 1000);
testRange (0, ULONG_MAX);
testRange (ULONG_MAX, ULONG_MAX);
return 0;
}
As you will see from the output, this gives the correct counts for various ranges:
In range 1000..10, found 0 occurrences
In range 0..0, found 0 occurrences
In range 9..9, found 1 occurrences
In range 3..1000, found 6 occurrences
In range 0..18446744073709551615, found 41 occurrences
In range 18446744073709551615..18446744073709551615, found 0 occurrences
And, if you uncomment the printf line in countPowersOfThreeBetween(), you'll also see the actual values detected.
Before choosing floating point types in the future, I strongly recommend you read this article entitled "What every computer scientist should know about floating-point arithmetic", by David Goldberg. It explains your problem(s) nicely, much better than I could have.
You don't actually need floating point (or negative integer) types here, so they should be avoided. Form your powers by multiplication, rather than addition:
#include <assert.h>
#include <limits.h>
#include <stdio.h>
int main(void){
unsigned int start, end, i, count = 0;
printf("Enter start and end: ");
int x = scanf("%u %u", &start, &end);
assert(x == 2); // XXX: INSERT PROPER ERROR HANDLING!
// find the first power greater than or equal to start
for (i = 1; i < start && UINT_MAX / 3 >= i; i *= 3);
// ... then count each one less than or equal to end
while (i <= end && UINT_MAX / 3 >= i) {
printf("%u\n", i);
i *= 3;
count++;
}
printf("Answer = %u\n", count);
}
Your problem is round-off error while float calculating in computer, the result of log(243)/log(3) is not exactly log3(243), where computer store approximate value of it. eg, in my 32bit computer, it is 4.99999999999999911182.
However, you have two ways to solve it,
use integer calculation instead of float.
simple mathematical transformation.
number of powers of 3 in [start, end] is equivalent to floor(log3(end)-log3(start))+1, wrote in c is
printf("answer:%d\n", (int)((log(1000)-log(3))/log(3))+1);
complete code:
#include <stdio.h>
#include <math.h>
int pow3(int n) {
int ret = 1;
while(n--) {
ret *= 3;
}
return ret;
}
int main() {
int a, start, end, answer;
scanf("%d%d", &start, &end);
a = (int)(log(start+0.5)/log(3));
//printf("%d,%d,%d\n", a, pow3(a), start);
if(start == end) answer = (start == pow3(a));
else answer = (int)((log(end+0.5)-log(start))/log(3))+1;
printf("answer = %d\n", answer);
}
Result:
Input[0]: 2 10
Output[0]: 2
Input[1]: 1 3
Output[1]: 2
Input[2]: 3 1000
Output[2]:6
Your program fails because of floating point precision issues.
Use integer arithmetics instead:
#include <limits.h>
#include <stdio.h>
int main(void) {
unsigned int start, end, i, count;
printf("Enter start and end: ");
if (scanf("%u %u", &start, &end) == 2) {
for (i = 1, count = 0; i <= end && i <= UINT_MAX / 3; i *= 3) {
if (i >= start) {
printf("%u\n", i);
count++;
}
}
printf("Answer = %u\n", count);
}
return 0;
}
A direct solution with floating point arithmetics is possible too:
#include <math.h>
#include <stdio.h>
int main(void) {
unsigned int start, end, count = 0;
printf("Enter start and end: ");
if (scanf("%u %u", &start, &end) == 2) {
if (end > 0 && end >= start) {
int start3 = (start <= 1) ? 0 : (int)(log(start - 0.5) / log(3));
int end3 = (int)(log(end + 0.5) / log(3));
count = end3 - start3;
}
printf("Answer = %u\n", count);
}
return 0;
}

Reverse two numbers and obtain the reverse of the sum

I am coming to SO as a last resort. Been trying to debug this code for the past 2 hours. If the question is suited to some other SE site, please do tell me before downvoting.
Here it goes:
#include <stdio.h>
#include<math.h>
int reverse(int n) {
int count = 0, r, i;
int k = (int)log(n * 1.0);
for(i = k; i >= 0; i--)
{
r = (n % 10);
n = (n / 10);
count = count + (r * pow(10, k));
}
return count;
}
int main(void) {
int t;
scanf("%d", &t);
while(t--)
{
int m, n, res;
scanf("%d %d", &m, &n);
res = reverse(m) + reverse(n);
printf("%d", reverse(res));
}
return 0;
}
My objective is to get 2 numbers as input, reverse them, add the reversed numbers and then reverse the resultant as well.I have to do this for 't' test cases.
The problem: http://www.spoj.com/problems/ADDREV/
Any questions, if the code is unclear, please ask me in the comments.
Thank you.
EDIT:
The program gets compiled successfully.
I am getting a vague output everytime.
suppose the 2 numbers as input are 24 and 1, I get an output of 699998.
If I try 21 and 1, I get 399998.
Okay, if you had properly debugged your code you would have notices strange values of k. This is because you use log which
Computes the natural (base e) logarithm of arg.
(took from linked reference, emphasis mine).
So as you are trying to obtain the 'length' of the number you should use log10 or a convertion (look at wiki about change of base for logarithms) like this: log(x)/log(10) which equal to log10(x)
And now let's look here: pow(10, k) <-- you always compute 10^k but you need 10^i, so it should be pow(10, i) instead.
Edit 1: Thanks to #DavidBowling for pointing out a bug with negative numbers.
I don't know how exactly you have to deal with negative numbers but here's one of possible solutions:
before computing k:
bool isNegative = n < 0;
n = abs(n);
Now your n is positive due to abs() returning absolute value. Go on with the same way.
After for loop let's see if n was negative and change count accordingly:
if (isNegative)
{
count = -count;
}
return count;
Note: Using this solution we reverse the number itself and leave the sign as it is.
It looks like Yuri already found your problem, but might I suggest a shorter version of your program? It avoids using stuff like log which might be desirable.
#include <stdio.h>
int rev (int n) {
int r = 0;
do {
r *= 10;
r += n % 10;
} while (n /= 10);
return r;
}
int main (void) {
int i,a,b;
scanf("%d",&i);
while (i--) {
scanf("%d %d",&a,&b);
printf("%d\n",rev(rev(a) + rev(b)));
}
return 0;
}
Hopefully you can find something useful to borrow! It seems to work okay for negative numbers too.
Under the hood you get char string, reverse it to numeric, than reverse it to char. Since is more comfortable work with chars than let's char:
char * reverse (char *s,size_t len) //carefull it does it in place
{
if (!len) return s;
char swp, *end=s+len-1;
while(s<end)
{
swp =*s;
*s++=*end;
*end--=swp;
}
return s;
}
void get_num(char *curs)
{
char c;
while((c=getchar())!='\n')
*curs++=c;
*curs=0;
}
int main()
{
double a,b,res;
char sa[20],sb[20],sres[20],*curs;
get_num( sa);
get_num(sb);
reverse(sa,strlen(sa));
reverse(sb,strlen(sb));
sscanf(sa,"%f",&a);
sscanf(sb,"%f",&b);
res=a+b;
sprintf(sres,"%f",res);
reverse(sres);
printf(sres);
}

Recursion with Max Integer

I am writing a program to calculate the factorial of a number. I am using recursion to solve this problem. The problem I am running into is that once I reach number 13, it will throw garbage numbers because of INT's limit. What I want to do is implement a way to catch the error when it happens (without hard cording that at x=13 it has to stop, but rather by the output). This is my attempt:
#include <stdio.h>
int factorial( int n)
{
printf("Processing factorial( %d )\n", n);
if (n <= 1)
{
printf("Reached base case, returning...\n");
return 1;
}
else
{
int counter = n * factorial(n-1); //Recursion to multiply the lesser numbers
printf("Receiving results of factorial( %d ) = %d * %d! = %d\n", n, n, (n-1), counter);
if( counter/n != factorial(n-2) ) //my attempt at catching the wrong output
{
printf("This factorial is too high for this program ");
return factorial(n-1);
}
return counter;
printf("Doing recursion by calling factorial (%d -1)\n", n);
}
}
int main()
{
factorial(15);
}
The problem with this is that the program now never terminates. It keeps on looping and throwing me random results.
Since I cannot answer my own question, I will edit with my solution:
int jFactorial(int n)
{
if (n <= 1)
{
return 1;
}
else
{
int counter = n *jFactorial(n-1);
return counter;
}
}
void check( int n)
{
int x = 1;
for(x = 1; x < n+1; x++)
{
int result = jFactorial(x);
int prev = jFactorial(x-1);
if (((result/x) != prev) || result == 0 )
{
printf("The number %d makes function overflow \n", x);
}
else
{
printf("Result for %d is %d \n", x, result);
}
}
}
A better way to do it:
if (n <= 1) {
return 1;
} else {
int prev_fact = factorial(n - 1);
if (INT_MAX / prev_fact < n) { /* prev_fact * n will overflow */
printf("Result too big");
return prev_fact;
} else {
return prev_fact * n;
}
}
Uses a more accurate check (I hope) for whether the multiplication will overflow, and doesn't add any more calls to factorial.
Update
After looking more closely, turns out I missed the fact that gmp is also implemented for C. Here is the solution in C
I've been able to run it on my macbook pro, using homebrew to install gmp (brew isntall gmp)
#include <gmp.h>
#include <stdio.h>
void factorial(mpz_t ret, unsigned n) {
if (n <= 1) {
mpz_set_ui(ret, 1);//Set the value to 1
} else {
//multiply (n-1)! with n
mpz_t ret_intermediate;
mpz_init (ret_intermediate);//Initializes to zero
factorial(ret_intermediate, n-1);
mpz_mul_ui(ret, ret_intermediate, n);
}
return;
}
int main(){
mpz_t result;
mpz_init (result);
factorial(result, 100);
char * str_result = mpz_get_str(NULL, 10, result);
printf("%s\n", str_result);
return 0;
}
Original Answer
After quick googling, I found the following solution. Note this is a C++ solution. I briefly descirbe how you could do the same thing in ANSI C at the bottom.
Big numbers library in c++
https://gmplib.org/ This c++ library can work on numbers arbitrarily large.
Checkout https://gmplib.org/manual/C_002b_002b-Interface-General.html
The whole code could look something like....
#include <gmpxx.h>
#include <iostream>
mpz_class factorial(unsigned n) {
if (n <= 1) return mpz_class(1);
return mpz_class(n) * factorial(n-1);
}
int main(){
mpz_class result = factorial(100);
std::string str_result = result.get_str();
std::cout << str_result << std::endl;
return 0;
}
The ANSI C Version
You could implement the same thing using ansi C, with a structure to hold expanding list of numbers(using linked-list or any other expandable arraylist containers), and you'd only need to implement three methods... initialize, multiply and convert to string.

Resources