Long precise numbers in C? - c

I am making a program that prints the first 100 Lucas numbers(they are like Fibonacci), but the last few numbers don't fit in unsigned long long int. I tried using long double, but it isn't precise and I get some differences with what I am supposed to get.
This is a homework task and my teacher specifically specified we do not need to use any other library than stdio.h.
I tried making a method that adds strings as numbers, but it is way beyond out experience and I sincerely doubt that is what we have to do.
With imprecisions it looks something like this:
#include <stdio.h>
int main()
{
long double firstNumber = 2;
long double secondNumber = 1;
long double thirdNumber;
int i;
for (i = 2; i <= 100; i += 1)
{
thirdNumber = secondNumber + firstNumber;
firstNumber = secondNumber;
secondNumber = thirdNumber;
printf("%Lf, ", thirdNumber);
}
return 0;
}

It looks like all you need is addition. I see three ways you can go about this.
If you weren't forbidden from using libraries then you'd use one of the many bigint libraries commonly available.
Implement a string-based adder. You'd basically implement the addition method you learned in 3rd grade.
As a hack, if your largest number fits in roughly two unsigned long long ints then you can split your number up into Most Significant Digits and Least Significant Digits. I'd go this route.

I used below to store really large numbers in an array. Pasting the code below with some comments. Hope it helps.
#include<stdio.h>
int main()
{
int t;
int a[200]; //array will have the capacity to store 200 digits.
int n,i,j,temp,m,x;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
a[0]=1; //initializes array with only 1 digit, the digit 1.
m=1; // initializes digit counter
temp = 0; //Initializes carry variable to 0.
for(i=1;i<=n;i++)
{
for(j=0;j<m;j++)
{
x = a[j]*i+temp; //x contains the digit by digit product
a[j]=x%10; //Contains the digit to store in position j
temp = x/10; //Contains the carry value that will be stored on later indexes
}
while(temp>0) //while loop that will store the carry value on array.
{
a[m]=temp%10;
temp = temp/10;
m++; // increments digit counter
}
}
for(i=m-1;i>=0;i--) //printing answer
printf("%d",a[i]);
printf("\n");
}
return 0;
}

Related

Issues with using nested loops to find strong numbers between two user input numbers

So I am new to C, and have been doing some practice, and nested loops tend to be tougher for me.
This new problem about finding a strong number between two user input numbers is confusing me.
Essentially, a strong number is a number whose individual digit's factorials add up to the number. e.g. 145 = 1! + 4! + 5! = 1 + 24 + 120.
My issue is that after I input the two numbers, absolutely nothing happens. I am trying to print all strong numbers in between a range.
I have been trying to break the code down by pieces, and added comments to actually make it easier to understand for myself and others.
I am using the following function to find the strong numbers, the int main() just has the user input statements:
void strongno(int num1, int num2)
{
// num1 and num2 are from user input in the in main() function
int tot = 0; // to store the total number from each digits factorials
for(int i = num1; i < num2; i++)
//getting each individual number in the range, say i = 145
{
while(i)
{
int rem, fact = 1;
rem = i % 10;// I am using this to get each digit alone, so first we get 5
for(int j = 1; j <= rem; j++)
{
fact = fact * j;
//the fact will give us the factorial of 5 = 120
}
tot = tot + fact; //tot will add all of the factorials of each remainder
// while the number is not 0, so for now it is 120
i = i / 10; // this will give us 14, and the cycle will repeat
}
// Once we have our total, we will compare the actual number i
// to our calculated total. If it matches, it is a strong number
if(tot == i)
{
printf("Strong Number: %d\n", i);
}
else
{
continue;
}
}
}
I feel that the main issue may be with where I am actually placing the if statement or something, however I have tried arranging it and to no avail. The loops make sense to me, how they interact and all. I am trying not to look at the solution for this question, as that never helps, and would prefer guidance with the code I have, to work on a proper solution. Anything is appreciated.
For starters it is better to declare the function with parameters of the unsigned type unsigned int instead of the signed type int
void strongno( unsigned int num1, unsigned int num2);
Otherwise you will have problems with negative numbers.
Using this while loop
while(i)
does not make a sense because it changes the variable i used in the preceding for loop. You need to use some intermediate variable that will assigned with the value of i.
For example
for( ; num1 < num2; num1++)
//getting each individual number in the range, say i = 145
{
unsigned int i = num1;
//...
Also the variable tot should be declared and initialized where it is used that is within the outer for loop.
for( ; num1 < num2; num1++)
//getting each individual number in the range, say i = 145
{
unsigned int i = num1;
unsigned int tot = 0; // to store the total number from each digits factorials
//...
And this else statement
else
{
continue;
}
is just redundant. Remove it.

Tricky and confusing C program about divisor sum and perfect numbers

The assignment is :
Write a program that calculates the sum of the divisors of a number from input.
A number is considered perfect if the sum of it's divisiors equal the number (ex: 6 = 1+2+3 ;28 = 1 + 2 + 4 + 7 +14).
Another definition:
a perfect number is a number that is half the sum of all of its positive divisors (including itself)
Generate the first k perfect numbers (k<150).
The main problem with this is that it's confusing the two asking points don't really relate.
In this program i calculated the sum of divisors of an entered number, but i don't know how to relate it with the second point (Generate the first k perfect numbers (k<150)).
#include <stdio.h>
#include <stdlib.h>
main()
{
int x,i,y,div,suma,k;
printf("Introduceti numarul\n"); \\enter the number
scanf("%d",&x);
suma=0; \\sum is 0
for(i=1;i<=x;i++)
{
if(x%i==0)
suma=suma+i; \\sum=sum+i;
}
printf("Suma divizorilor naturali este: %d\n",suma); \\the sum of the divisors is
for(k=1;k<150;k++) \\ bad part
{
if (x==suma)
printf("%d",k);
}
}
Suppose you have a function which can tell whether a given integer is perfect or not:
int isPerfect(int);
(function body not shown)
Now your main program will look like:
int candidate;
int perfectNumbers;
for(candidate = 1, perfectNumbers = 0; perfectNumbers < 150; candidate++) {
if (isPerfect(candidate)) {
printf("Number %d is perfect\n", candidate);
perfectNumbers++;
}
}
EDIT
For the same program without functions:
int candidate;
int perfectNumbers;
for(candidate = 1, perfectNumbers = 0; perfectNumbers < 150; candidate++) {
[... here your algorithm to compute the sum of the divisors of "candidate" ...]
if (candidate*2 == sum_of_divisors) {
printf("Number %d is perfect\n", candidate);
perfectNumbers++;
}
}
EDIT2: Just a note on perfect numbers
As noted in the comments section below, perfect numbers are very rare, only 48th of them are known as of 2014. The sequence (A000396) also grows very fast: using 64-bit integers you'll be able to compute up to the 8th perfect number (which happen to be 2,305,843,008,139,952,128). In this case the variable candidate will wrap around and start "finding" "new" perfect numbers from the beginning (until 150 of them are found: actually 19 repetitions of the only 8 findable in 64-bit integers). Note though that your algorithm must not choke on a candidate equals to 0 or to negative numbers (only to 0 if you declare candidate as unsigned int).
I am interpreting the question to mean generate all numbers under 150 that could are perfect numbers.
Therefore, if your program works for calculating perfect numbers, you keep calculating them until the starting number is >= 150.
Hope that makes sense.
Well, here's my solution ..
First, you have to make a reliable way of getting divisors.Here's a function I made for that:
size_t
getdivisors(num, divisors)
long long num;
long long *divisors;
{
size_t divs = 0;
for(long long i = num; i > 0; --i)
if (num%i == 0)
divisors[divs++] = i;
return divs;
}
Second, you need to check if the number's divisors match the perfect number's divisors properties (the sum of them is half the number).
Here's a second function for that:
bool
isperfect(num)
long long num;
{
long long divisors[num/2+1];
size_t divs = getdivisors(num, divisors);
if (divs == 0)
return false;
long long n = 0;
for(int i = 1; i < divs; ++i)
n += divisors[i];
return (n == num);
}
Now, from your question, I think you need to print all perfect numbers less than 150, right ?
See this:
int
main(argc, argv)
int argc;
char ** argv;
{
for(int i = 1; i < 150; ++i)
if (isperfect(i))
printf("%d is perfect.\n", i);
return 0;
}
I hope that answers your question ..

Program to reverse a number without using an array

This is the code that I used. It works perfectly, but I don't understand why it works. I just kept changing my original logic until I started using -1 in the counter loop.
#include<stdio.h>
#include<math.h>
int main(){
int number, reverse, sum =0;
scanf("%d", &number);
int temp = number;
int ctr;
for(ctr = -1; temp!=0; ctr++)
temp = temp/10;
while(number)
{
sum = sum + (number%10 * (pow(10, ctr--)));
number = number/10;
}
printf("%d", sum);
return 0;
}
same basic math but so much easier to understand:
unsigned int number = 123456789;
unsigned int reversed = 0;
do {
reversed *= 10;
reversed += number % 10;
number /= 10;
} while (number > 0);
Although this is kind of awkward to explain the logic of the code that you wrote it yourself, I understood the logic behind it.
Indeed, I was looking for a solution to solve this problem: How to reverse any positive integer without using arrays or indexed variables to which your code was the solution I was looking for.
The logic of your programme is like this:
you first count the digits of the given number in the FOR-loop in the shortest possible way. you need this because you have to 10-power each remainder up to digits of the given number in the next WHILE-loop and you store/add the result of this each time in the variable named SUM. The final result of this would be the whole integer to be reversed.
PS1:
You do not need the variable named REVERSE. Just drop it or replace SUM with it.
PS2:
You really do not need to go that long way to do this. Here's another shorter version:
#include <stdio.h>
void main (void){
unsigned short int uNum, nReversed;
puts ("Enter a positive integer number: ");
scanf ("%hu", &uNum);
while (uNum != 0){
nReversed = uNum%10 + nReversed*10 ;
uNum /= 10;
}
printf ("\n\n\nThat is %d", nReversed);
}

High-precision program that calculates 2^n

I'm building a program in C that can get powers of 2. The user inputs the value of n, and the program calculates 2^n.
Here's the code.
The problem comes when I input 100
What I am getting:
1,267,650,600,228,229,400,000,000,000,000
What I should get
1,267,650,600,228,229,401,496,703,205,376
It has to be coded entirely in ANSI C. Any ideas on how to increase the precision? The maximum value of N has to be 256 (256 bits, I imagine, which means the maximum output should be 2^256).
What I'm lacking here is precision, and I don't know how to fix that. Any ideas?
I think it's easiest if you work in base 10 from the start. This is because while calculating powers of 2 in binary is trivial, the conversion back to base 10 is a lot harder.
If you have an array of base 10 digits1, you only need to implement base 10 addition with carry to be able to multiply by 2 (by adding the number to itself). Do that n times in a loop and you have your answer.
If you wish to support higher exponents, you can also look into implementing exponentiation by squaring, but that's harder, since you'll need general multiplication, not just by 2 for that.
1 Tip: It's more convenient if you store the digits in reverse order.
Here is my quick and dirty implementation of hammar's approach., storing the decimal number as a C string with the digits in reverse order.
Run the code on ideone
void doubleDecimal(char * decimal)
{
char buffer[256] = "";
char c;
unsigned char d, carry = 0;
int i = 0;
while (c = decimal[i])
{
d = 2 * (c - '0') + carry;
buffer[i] = (d % 10) + '0';
carry = d / 10;
i++;
}
if (carry > 0)
buffer[i++] = (carry % 10) + '0';
buffer[i] = '\0';
strncpy(decimal, buffer, 256);
}
void reverse(char * str)
{
int i = 0;
int j = strlen(str) - 1;
while (j > i)
{
char tmp = str[i];
str[i] = str[j];
str[j] = tmp;
i++;
j--;
}
}
int main(void)
{
char decimal[256] = "1";
int i;
for (i = 0; i < 100; i++)
doubleDecimal(decimal);
reverse(decimal);
printf("%s", decimal);
return 0;
}
Output:
1267650600228229401496703205376
double is a (probably) 64bit value. You can't store 256 bits of precision in 64 bits. The reason that you are getting a number that is sort of close is because floating point numbers are stored with varying precision -- not all sequential numbers can be represented, but you can represent very large numbers. Pretty useless in this case.
What you want is either to use an arbitrary precision library or, since this is probably homework, you are expected to write your own.
A typical double, using 64-bit IEEE 754, has about 51 bits precision, IIRC.
Most probably the point of supporting exponents up to 256 is to exceed that precision, and also the precision of a long double or long long, so that you have to do things yourself.
As a homework exercise, then,
Store decimal digit values in an array + a digit count
Implement doubling of the value in such array + count
Start with 1 and double value appropriate number of times.
A few things you'll want to think about to solve this:
You are only dealing with integers so you should use an integer
representation (you will need to roll your own because you can't use
long long which is "only" 64 bits long).
Powers of 2 you say -how convenient - computers store numbers using powers of 2 (you'll
only need to use shift operations and bit fiddling .... no
multiplications will be needed).
How can you convert a base 2 number to a base 10 number for display purposes (think of division and outputting one number at a time (think about what a hardware divisor does in order to get the bit manipulations correct).
You can't the store 256 bits of precision in 64 bits. Reason that you are getting a number to close is because floating point numbers are stored with varying precision. To all sequential numbers can be represented, but you can represent very large numbers. Pretty useless in this case.
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//constants
#define MAX_DIGITS 1000
//big integer number struct
struct bigint {
char Digits[MAX_DIGITS];
};
//assign a value
void assign(struct bigint* Number,int Value) {
if (Value!=1) {
printf("Can not assign value other than 1\n");
exit(0);
}
memset(Number,0,sizeof(bigint));
Number->Digits[0] = Value;
}
//multiply the big integer number with value
void multiply(struct bigint* Number,int Value) {
int Digit,New_Digit;
int Carry = 0;
for (int Index=0; Index<MAX_DIGITS; Index++) {
Digit = Number->Digits[Index];
New_Digit = Digit*Value%10;
if (New_Digit+Carry<10) {
New_Digit = New_Digit+Carry;
Carry = Digit*Value/10;
}
else {
New_Digit = (New_Digit+Carry)%10;
Carry = (Digit*Value/10)+1;
}
//set the new digit
Number->Digits[Index] = New_Digit;
}//for loop
}
//print out the value of big integer type
void print(struct bigint* Number) {
int Index = MAX_DIGITS-1;
while (Number->Digits[Index]==0 && Index>=0)
Index--;
//the big integer value is zero
if (Index==-1) {
printf("0");
return;
}
while (Index>=0) {
printf("%u",Number->Digits[Index]);
Index--;
}
}
//main programme entry point
int main(int Argc,char** Args) {
int Power = 100;
struct bigint Number;
//assign the initial value
assign(&Number,1);
//do the multiplication
for (int Index=0; Index<Power; Index++)
multiply(&Number,2);
//print result
print(&Number);
getch();
}
//END-OF-FILE

Pascal's triangle in C with combinations

#include <stdio.h>
long factorial(int num)
{
int counter;
int fact = 1;
for (counter = num; counter > 0; counter--) fact *= counter;
return fact;
}
float combinations(int n, int k)
{
int numerator = factorial(n);
int denominator = factorial(k) * factorial(n-k);
float fraction = numerator/denominator;
return fraction;
}
int main()
{
printf("How many rows of Pascal\'s triangle should I print?\t");
int rows = GetInteger();
int counter;
int counter2;
for (counter = 1; counter <= rows; counter++)
{
int y = rows-counter;
for (; y > 0; y--) printf(" ");
for (counter2 = 0; counter2 <= counter; counter2++)
printf("%6.0lu", (long) combinations(counter, counter2));
printf("\n");
}
}
Every time I go past twelve rows, the numbers start to decrease. What am i doing wrong?
And, GetInteger() is just a scanf() with a few touch ups. I am 100% sure it works perfectly.
After 12th row factorial and so pascal triangle elements become too large so int type cannot hold them - so you get overflow (most probably values you get are wrapped around maximum int value).
P.S. why do you use 3 different types in your code (long, int, float)? As k!*(n-k)! always divides n! you do not need float value (you use integer division and cast result to long anyway). Just use the biggest integer type you can, or some custom BigInt type that can hold integer numbers of arbitrary length - so you can show correct values for large row numbers.
Don't start from factorials. Start from the following facts about Pascal's triangle:
the nth row of the triangle has n elements (if we start counting from 1)
the first and last elements of each row are 1
each element aside from the first and last one is the sum of the two elements diagonally above it (if the triangle is written in a symmetric way)
You will of course be limited by the size of the data type you are holding results in, but not any sooner than necessary (by intermediate results such as factorials).
INT_MAX is usually 2,147,483,647
12! is 479,001,600
13! is 6,227,020,800 but your function factorial(13) returns 1,932,053,504 (= 6,227,020,800 - 4,294,967,296)

Resources