C: how to break apart a multi digit number into separate variables? - c

Say I have a multi-digit integer in C. I want to break it up into single-digit integers.
123 would turn into 1, 2, and 3.
How can I do this, especially if I don't know how many digits the integer has?

int value = 123;
while (value > 0) {
int digit = value % 10;
// do something with digit
value /= 10;
}

First, count the digits:
unsigned int count(unsigned int i) {
unsigned int ret=1;
while (i/=10) ret++;
return ret;
}
Then, you can store them in an array:
unsigned int num=123; //for example
unsigned int dig=count(num);
char arr[dig];
while (dig--) {
arr[dig]=num%10;
num/=10;
}

As a hint, getting the nth digit in the number is pretty easy; divide by 10 n times, then mod 10, or in C:
int nthdig(int n, int k){
while(n--)
k/=10;
return k%10;
}

The last digits of 123 is 123 % 10.
You can drop the last digit of 123 by doing 123/10 -- using integer division this will give you 12.
To answer your question about "how do I know how many digits you have" --
try doing it as described above and you will see how to know when to stop.

I think below piece of code will help....
temp = num;
while(temp)
{
temp=temp/10;
factor = factor*10;
}
printf("\n%d\n", factor);
printf("Each digits of given number are:\n");
while(factor>1)
{
factor = factor/10;
printf("%d\t",num/factor);
i++;
num = num % factor;
}

//Based on Tony's answer
#include <stdio.h>
int nthdig(int n, int k){
while(n--)
k/=10;
return k%10;
}
int main() {
int numberToSplit = 987;
printf("Hundreds = %i\n",nthdig(2, numberToSplit));
printf("Tens = %i\n",nthdig(1, numberToSplit));
printf("Units = %i\n",nthdig(0, numberToSplit));
}
This results in the following printout:
Hundreds = 9
Tens = 8
Units = 7

I made this based on the code from #asaelr:
typedef struct digitsArrayPlusNumber {
uint32_t *baseAddress;
uint32_t number;
} digitsArrayPlusNumber;
digitsArrayPlusNumber *splitDigits (uint32_t inValue) {
// based on code from asaelr#stackoverflow.com
uint32_t inputValue = inValue;
//Count digits
uint32_t theCount = 1;
while (inputValue /= 10)
theCount++;
// put in array
uint32_t *arr = malloc(sizeof(uint32_t) * theCount);
uint32_t dig = theCount;
while (dig--) {
arr[dig]=inValue % 10;
inValue /= 10;
// printf ("%d\n", arr[dig]);
}
digitsArrayPlusNumber *dandn = malloc (sizeof(digitsArrayPlusNumber));
dandn->baseAddress = arr;
dandn->number = theCount;
return dandn;
}
int main(int argc, const char * argv[]) {
for (int d = 0; d < splitDigits(12345678)->number; d++)
printf ("%u\n", (splitDigits(12345678)->baseAddress)[d]);
}
It works quite well, thanks!

You can use %10, which means the remainder if the number after you divided it. So 123 % 10 is 3, because the remainder is 3, substract the 3 from 123, then it is 120, then divide 120 with 10 which is 12. And do the same process.

we can use this program as a function with 3 arguments.Here in "while(a++<2)", 2 is the number of digits you need(can give as one argument)replace 2 with no of digits you need. Here we can use "z/=pow(10,6)" if we don't need last certain digits ,replace 6 by the no of digits you don't need(can give as another argument),and the third argument is the number you need to break.
int main(){
long signed c=0,z,a=0,b=1,d=1;
scanf("%ld",&z);
while(a++<2){
if(d++==1)
z/=pow(10,6);
c+=(z%10)*b;
z/=10;
b*=10;}
return c;}

You can divide and conquer but you have rewrite all of arithmetic libraries. I suggest using a multi-precision library https://gmplib.org But of course it is good practice

Related

I need to calculate the reverse of a number using pointers to functions

So I need to calculate the reverse of a number using pointers in a function. I get junk memory when I run it.Here is what I tried.(When I remove the p ,it works, I don't get any junk memory but than I can calculate only the remainder , I don't get why?)
I m sorry for the earlier post. I read the rules of Stack Overflow.
Here is the code:
int Invers(int x , int *Calculinvers ){
int rem = 0;
int p = 1
while(x!=0){
rem = x % 10 ;
*Calculinvers = p*10 + rem;
x = x / 10;
}
return *Calculinvers;
}
int main(){
int a;
printf("Introduceti numarul caruia vreti sa-i calculati inversul : \n");
scanf("%d" , &a);
int Calcul;
Invers(a , &Calcul);
printf("Inversul numarului este : %d\n" , Calcul);
return 0;
}
Two problems and fixes:
(1)*Calculinvers needs to be initialized to 0, or system will give you unexpected value.
(2)Replace *Calculinvers = p*10 + rem; to *Calculinvers = *Calculinvers*10 + rem; because you did not add the previous value.
I threw together this, it seems to work:
#include <stdio.h>
int reverse(int x)
{
out = 0;
while (x != 0)
{
const int ones = x % 10;
out *= 10;
out += ones;
x /= 10;
}
return out;
}
int main(void) {
const int num[] = { 0, 1, 10, 47, 109, 4711, 1234, 98765432 };
printf("I got:\n");
for (int i = 0; i < sizeof num / sizeof *num; ++i)
{
printf(" %d -> %d\n", num[i], reverse(num[i]));
}
return 0;
}
It prints:
I got:
0 -> 0
1 -> 1
10 -> 1
47 -> 74
109 -> 901
4711 -> 1174
Obviously when we're working with actual integers, trailing zeroes turn into leading zeroes which don't really exist unless we store the original number's length and pad when printing. That's why 10 turns to 1, for instance.
This is better suited as a pure string-space operation, since then each digit exists as part of the string rather than as part of the representation of a number (which has other conventions).
Update:
If you really want to use pointers, you can of course wrap the above in a more pointery shroud:
void reverse_at(int *x)
{
const int rev = reverse(*x);
*x = rev;
}
but as stated in comments (and hopefully illustrated by my code) a more functional approach where the return value calues the result of a function is generally more easily understood, safer, and just better.

How do I save the return array from a function?

I'm currently learning c (just starting), and I'm trying to create a program that finds all the integers with 10 digits, with the conditions:
the first digit can be divided by 1;
the number represented by the first two digits can be divided by 2;
etc.
For example, the number 1295073846 doesn't make the cut, because 1295 is not divisible by 4 (but 1 is divisible by 1, 12 by 2, and 129 by 3).
I understand how this can be done, but I'm still struggling to manipulate arrays and pointers. Here is my code (only numToArr and the beginning of findn() should be relevant):
int numToArr(long num) { // splits a given number into an array of 10 digits
int arr[10];
int i = 9;
do {
arr[i] = num % 10;
num /= 10;
i--;
} while (num != 0);
printf("%d%d%d\n", arr[0], arr[1], arr[2]);
return *arr;
}
int join(char s[3], int n1, int n2) { // so I can get the combination of digits
snprintf(s, 3, "%d%d", n1, n2);
int n12 = atoi(s);
return n12;
}
int findn() { // the output will be the list of numbers, but I'm testing with 1292500000
long nmin = 1000000000;
long nmax = 9999999999;
int *arr;
for(int i = nmin; i <= nmax; i++) {
*arr = numToArr(1292500000l);
// I know I can optimize this part, will work on it later
if(arr[0] % 1 != 0) // if the first digit is not divisible by one, skip to the next number
continue;
else { // if it is, check for the combination of the first two digits
char s12[3];
int n12 = join(s12, arr[0], arr[1]);
printf("%d\n", n12);
break;
...
When I do
*arr = numToArr(1292500000l);
the array doesn't have the correct digits (arr[0] should be 1, arr[1] should be 2 (but it's zero)).
I've tried messing with pointers and everything I could find online to solve this issue, but nothing works. Any help would be appreciated!
Thank you.

Weird pattern when I try to generate a 4-digit integer for which every digit is distinct

When I try to write a small program in C language that is intended to generate a 4-digit integer for which every digit is distinct and nonzero, the returned value is always in pattern like 1abc: the first digit seems to always be 1, and sometimes the returned value will be more than 4-digit like 56127254. Could anyone help me look into this? Thank you very much in advance.
So basically the program includes two functions, int isvalid(int n) and int choose_N(void).
isValid return 1 if the integer consists of exactly 4 decimal digits, and all these digits are nonzero and distinct, and 0 otherwise.
And int choose_N(void) generates an integer that is 4-digit and all the digits are distinct and nonzero.
Here is my code:
#define N_DIGITS 4
....
....//the main function
int isvalid(int n){
int i, x; int check[N_DIGITS]={0};
for(i=1;i<=N_DIGITS;i++){ //check whether all digits are nonzero
if((check[i-1]=n%10)==0){
return 0;
}
n /= 10;
}
for(i=0;i<N_DIGITS-1;i++){ // check whether all digits are distinct
for(x=i+1;x<N_DIGITS;x++){
if(check[i]==check[x])
return 0;
}
}
return 1;
}
int choose_N(void){
int i; int number=0;
while(!isvalid(number)){
for(i=0;i<N_DIGITS;i++){
srand(time(0));
number += ((10^i)*(rand()%10));
}
}
return number;
}
For srand(time(0));, I have tried various alternatives like srand(time(0)+i); or put this statement out of while loop, but those attempts seemingly did not work and still the returned value of choose_Nstill showed the werid pattern that I described.
your choose_N method has several issues:
First, if the number isn't valid, you're not resetting it to 0, so it just grows and grows.
Second, srand(time(0)) is not necessary within the loop (and could yield the same result for several iterations), just do it at program start (srand() — why call it only once?)
Third and biggest mistake: 10 ^ i is 10 xor i, not 10**i. You can use an aux value and multiply by 10 in your loop. Since number of digits is low, no risk of overflow
minor remark: you want to pass in the loop at least once, so use a do/while construct instead, so you don't have to force the first while test.
I'm trying to fix your code:
int choose_N(void){
int i, number;
do
{
number = 0;
int p = 1;
for(i=0;i<N_DIGITS;i++)
{
number += p*(rand()%10);
p *= 10;
}
} while(!isvalid(number));
return number;
}
While #Jean-François-Fabre answer is the right one, it is not optimal algorithm. Optimal algorithm in such case would be using FIsher-Yates-Knuth shuffle and Durstenfeld's implementation.
Shuffling right array will produce numbers which are automatically valid, basically no need for isvalid(n) anymore.
Code
// Swap selected by index digit and last one. Return last one
int
swap_array(int digits[], int idx, int last) {
if (idx != last) { // do actual swap
int tmp = digits[last];
digits[last] = digits[idx];
digits[idx] = tmp;
}
return digits[last];
}
int
choose_N_Fisher_Yates_Knuth() {
int digits[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int r = 0;
for (int k = 0; k != N_DIGITS; ++k) {
int idx = rand() % (9 - k);
int n = swap_array(digits, idx, (9 - k) - 1);
r = r * 10 + n;
}
return r;
}
int
main() {
srand(12345);
int r, v;
r = choose_N_Fisher_Yates_Knuth();
v = isvalid(r);
printf("%d %d\n", r, v);
r = choose_N_Fisher_Yates_Knuth();
v = isvalid(r);
printf("%d %d\n", r, v);
r = choose_N_Fisher_Yates_Knuth();
v = isvalid(r);
printf("%d %d\n", r, v);
r = choose_N_Fisher_Yates_Knuth();
v = isvalid(r);
printf("%d %d\n", r, v);
return 0;
}
Output
7514 1
6932 1
3518 1
5917 1

Rounding off an integer to always end on 0

I'm making a program to calculate the number of perfect squares between 1 and another number, and I want the counter to take only the first number of the integer, and put 0 on the rest, e.g: Result of the calculation is 31, I want to display 30, if it's 190, then display 100, and so on.
int number;
int i = 1;
int perfectCounter = 0;
printf("Enter a number: ");
scanf("%d", &number);
while (i <= number) {
float tempSquare = sqrt(i);
int integerPart = tempSquare;
if (tempSquare == integerPart)
perfectCounter++;
i++;
}
printf("%d", perfectCounter);
That's the code that I have right now, if I insert 1000, it will display 31, and I want it to display 30, I can't think a solution for this.
Divide the number by the highest power of 10 below the number. Do this using integer arithmetic, so it gets the integer part of the division. Then multiply by the power of 10.
#include <math.h>
int powerOf10 = pow(10, (int)log10(perfectCounter));
int roundedCounter = (perfectCounter/powerOf10)*powerOf10;
printf("%d", roundedCounter);
You can use a function like this one to round your numbers. Basically what it does is it "chips away" one digit at a time until we are left with only one digit and then adds appropriate number of zeros to it:
int round(int _in){
int numDigits = 0;
while(_in > 9){
++numDigits;
_in /= 10;
}
int res = _in; // whatever is left would be the left-most digit
for(int i = 0; i < numDigits; ++i){
res *= 10;
}
return res;
}
Here's a simple solution with no math:
void print_rounded(int i) {
unsigned u = i;
if (i < 0) { putchar('-'); u = -i; }
char buf[2];
int n = snprintf(buf, 2, "%u", u);
for (putchar(buf[0]); --n; putchar('0')) {}
}
(In other words, print the first digit, and then print enough 0's to make up the length of the original number.)

What is Sum of Even Terms In Fibonacci (<4million)? [Large Value Datatype Confusion]

By starting with 1 and 2, the first 10 terms of Fibonacci Series will be:
1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
Find the sum of all the even-valued terms in the sequence which do not exceed 4 million.
Now, I got the idea for how to do this. But I'm confused about the data types to hold such big data. I'm getting weird results with int. :(
MORE: Its Project Euler 2nd question. But I can't get it. I get crazy values as answer. Can someone please post the ideal program?
EDIT: Here's what I wrote for just printing Fibonacci to screen. Bare Basic. My variable goes crazy even when I give 100 for the limit. Is my code wrong?
// Simple Program to print Fibonacci series in Console
#include <stdio.h>
int main() {
int x=1,y=2,sum=0,limit=0,i=0,temp=0;
printf("Enter Limit:");
scanf("%d",&limit);
if(limit==1)
printf("%d",x);
else if(limit>1) {
printf("%d %d",x,y);
if (limit>2) {
while (i<limit-2) {
temp=y;
sum=x+y;
x=temp;
y=sum;
printf(" %d",sum);
i++;
}
}
}
printf("\n");
return 0;
}
SOLVED: Actually, I managed to get the solution myself. Here's my program. It works.
#include <stdio.h>
int main() {
int x=1,y=2,sum,limit; //Here value of first 2 terms have been initialized as 1 and 2
int evensum=2; //Since in calculation, we omit 2 which is an even number
printf("Enter Limit: "); //Enter limit as 4000000 (4million) to get desired result
scanf("%d",&limit);
while( (x+y)<limit ) {
sum=x+y;
x=y;
y=sum;
if (sum%2==0)
evensum+=sum;
}
printf("%d \n",evensum);
return 0;
}
Since you only want up to four million, it's likely that int is not your problem.
It's quite possible that your program is buggy and that the data storage is just fine, so you should test your program on smaller values. For example, it's clear that the sum of the first three even terms is 44 (hint: every third term is even) so if you run your program with a cap of 50, then you should instantly get 44 back. Keep running small test cases to get confidence in the larger ones.
For security, use the 'long' data type; the C standard requires that to hold at least 4 billion, but on most machines, 'int' will also hold 4 billion.
enum { MAX_VALUE = 4000000 };
int sum = 0;
int f_n0 = 0;
int f_n1 = 1;
int f_n2;
while ((f_n2 = f_n0 + f_n1) < MAX_VALUE)
{
if (f_n2 % 2 == 0)
sum += f_n2;
f_n0 = f_n1;
f_n1 = f_n2;
}
printf("%d\n", sum);
I am not a programmer, but here's an adaptation to Leffler's code without the IF-criterion. It should work for MAX_VALUES above 2 (given there are no mistakes in programming syntax), based on a pattern I found in the even-only fibonacci series: 0,2,8,34,144,610,2584... so interestingly: f_n2 = 4*f_n1 + f_n0. This also means this program only needs 1/3rd of the calculations, since it doesn't even consider/calculate the odd fibonacci numbers.
enum { MAX_VALUE = 4000000 };
int sum = 2;
int f_n0 = 0;
int f_n1 = 2;
int f_n2 = 8;
while (f_n2 < MAX_VALUE)
{
sum += f_n2;
f_n0 = f_n1;
f_n1 = f_n2;
f_n2 = 4*f_n1 + f_n0;
}
printf("%d\n", sum);
Try changing this:
while (i<limit-2)
to this:
while (y<limit)
As written, your program is cycling until it gets to the 4 millionth Fibonacci number (i.e. when i gets to 4 million, though overflow obviously happens first). The loop should check to see when y (the larger Fibonacci number) becomes greater than 4 million.
Guys, I got the answer. I confirmed the result and int can handle it. Here's my program:
#include <stdio.h>
int main() {
int x=1,y=2,sum,limit; //Here value of first 2 terms have been initialized as 1 and 2
int evensum=2; //Since in calculation, we omit 2 which is an even number
printf("Enter Limit: "); //Enter limit as 4000000 (4million) to get desired result
scanf("%d",&limit);
while( (x+y)<limit ) {
sum=x+y;
x=y;
y=sum;
if (sum%2==0)
evensum+=sum;
}
printf("%d \n",evensum);
return 0;
}
Thx for all the replies and help. "Thinking on my feet" to the rescue :)
An amusing solution is to use the closed form for Fibonacci sequences and the closed form for geometric progressions. The end solution looks like this:
sum = ( (1-pow(phi_cb, N+1)) / (1-phi_cb) - (1-pow(onephi_cb,N+1)) / (1-onephi_cb)) / sqrt(5);
where
double phi = 0.5 + 0.5 * sqrt(5);
double phi_cb = pow(phi, 3.0);
double onephi_cb = pow(1.0 - phi, 3.0);
unsigned N = floor( log(4000000.0 * sqrt(5) + 0.5) / log(phi) );
N = N / 3;
with all the caveats regarding double to int-type conversions of course.
int is big enough for values in the millions on almost every modern system, but you can use long if you are worried about it. If that still gives you weird results, then the problem is with your algorithm.
Use BigInt.
Then again, unsigned int stores values up to over 4 billion, so you shouldn't be having any problems even with "sum of all fibonacci numbers up to 4 million" (which, obviously, has to be less than 8 mil)?
Your program prints F_1 + ..+ F_limit and not F_1 + ... F_n with F_n < limit as you described.
Check the Wikipedia article on Fibonacci Numbers and Sloane A000045: Fibonacci numbers grows exponentially. Checking this table F_48 = 4807526976 which exceeds int. F_100 is 354224848179261915075 which surely overflows even int64_t (your stack doesn't, though).
Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be:
1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.
int main()
{
long first = 1, second = 2, next, c;
int sum=0;
for ( c = 1 ; c <100000000; c++ )
{
next = first + second;
if(next>=4000000)
{
next= next-second;
break;
}
first = second;
second = next;
if(next%2==0){
sum=sum+next;
}
}
printf("the sum of even valued term is %d\n",sum+2);
}
Here's my program:
#include <iostream>
long int even_sum_fibonacci(int n){
int i = 8;
int previous_i = 2;
int next_i = 0;
long int sum = previous_i + i;;
while(n>next_i){
next_i = i*4 + previous_i;
previous_i = i;
i = next_i;
sum = sum + i;
}
return sum - next_i; //now next_i and i are both the bigger number which
//exceeds 4 million, but we counted next_i into sum
//so we'll need to substract it from sum
}
int main()
{
std::cout << even_sum_fibonacci(4000000) << std::endl;
return 0;
}
Because if you look at the fibonacci series (at the first few even numbers)
2 8 34 144 610 2584 ... you'll see that it matches the pattern that
next_number = current_number * 4 + previous_number.
This is one of solutions. So the result is 4613732
You can try the below code.
public static void SumOfEvenFibonacciNumbers()
{
int range = 4000000;
long sum = 0;
long current = 1;
long prev = 0;
long evenValueSum= 0;
while (evenValueSum< range)
{
sum = prev + current;
prev = current;
current = sum;
if (sum % 2 == 0 )
{
evenValueSum = evenValueSum+ sum;
}
}
Console.WriteLine(evenValueSum);
}
You can use the above code.
import numpy as np
M = [[0,1],[1,1]]
F = [[0],[1]]
s = 0
while(F[1][0] < 4000000):
F = np.matmul(M, F)
if not F[0][0]%2:
s+=F[0][0]
print(s)
We can do better than this in O(log n) time. Moreover, a 2 × 2 matrix and a two dimensional vector can be multiplied again in O(1) time. Therefore it suffices to compute Mn.
The following recursive algorithm computes Mn
If n = 0, return I2
If n = 1, return M.
If n = 2m.
Recursively compute N = Mm, and set P = N2.
If n = 2m+1, set P = PM.
Return P.
We have T(n) = T(n/2) + O(1), and by master's theorem T(n) = O(log n)
You can also use recurrence for Even Fibonacci sequence is:
EFn = 4EFn-1 + EFn-2
with seed values
EF0 = 0 and EF1 = 2.
SIMPLE SOLUTION WOULD BE:-
#include <iostream>
using namespace std;
int main(int argc, char** argv) {
int n1=1;
int n2=2;
int num=0,sum;
for (int i=1;i,n1<4000000;i++)
{
cout<<" "<<n1;
num=n1+n2;
if(!(n1%2))
{
sum+=n1;
}
n1=n2;
n2=num;
}
cout<<"\n Sum of even term is = "<<sum;
return 0;
}
Here's my offer, written in Java. I had been using a for loop whose exit value was 4000000 but realized early on there was a serious overflow for the sum of the numbers. Realizing the Fibonacci Number has to be less than 4 million (and not the sum), I changed to a while loop and got it:
class Main {
public static void main(String[] args) {
int counter = 0;
int fibonacciSum = 0, fibonacciNum = 0;
int previous = 1, secondPrevious = 0;
fibonacciNum = previous + secondPrevious;
while (fibonacciNum <= 4000000){
if (fibonacciNum % 2 == 0 ){
counter++;
fibonacciSum += fibonacciNum;
secondPrevious = previous;
previous = fibonacciNum;
}//ends if statement
else {
secondPrevious = previous;
previous = fibonacciNum;
}//ends else statement
fibonacciNum = previous + secondPrevious;//updates number
}//ends loop
System.out.println("\n\n\n" + fibonacciSum);
}//ends main method
}//ends Main

Resources