#include <cs50.h>
#include <stdio.h>
#include <string.h>
// Multiply every other digit by 2, starting with the number’s second-to-last digit, and then add those products’ digits together.
// Add the sum to the sum of the digits that weren’t multiplied by 2.
// If the total’s last digit is 0 (or, put more formally, if the total modulo 10 is congruent to 0), the number is valid!
// 4003600000000014 - VISA TEST
// 123456789
int length(long n);
int main(void)
{
long ccnumber = get_long_long("Number: ");
long x = 10; //Gets the 2nd digit.
long y = 1; //gets the first.
long sum1 = 0; //Holds the doubled sum.
long sum2 = 0; //Holds the undoubled sum.
int n = 8;
while (n > 0)
{
long cc1 = ccnumber / y;
cc1 = cc1 % 10;
long cc2 = ccnumber / x;
cc2 = cc2 % 10;
y = y * 100;
x = x * 100;
// Times CC2 by 2.
cc2 = cc2 * 2;
// Check if double digit then mine by 9, as to add the two digits together.
if (cc2 / 10 != 0)
{
cc2 = cc2 - 9;
}
sum1 = sum1 + cc2;
sum2 = sum2 + cc1;
}
}
I have tried checking if it is 0 before dividing by 10. I have tried some other checks with the cc1 and cc2 but cant work it out. I am doing the CS50 course and tring to do the Credit problem set, This is the best I have done so far but it is suddenly throwing this error since trying to do the next step of checking if the total %10 == 0.
The problem is really the infinite loop. But that, by itself, doesn't result in the core dump. What happens is best illustrated by adding a print statement at the bottom of the loop to display the values of a few variables:
#include <cs50.h>
#include <stdio.h>
#include <string.h>
// Multiply every other digit by 2, starting with the number’s second-to-last digit, and then add those products’ digits together.
// Add the sum to the sum of the digits that weren’t multiplied by 2.
// If the total’s last digit is 0 (or, put more formally, if the total modulo 10 is congruent to 0), the number is valid!
// 4003600000000014 - VISA TEST
// 123456789
int length(long n);
int main(void)
{
long ccnumber = get_long_long("Number: ");
long x = 10; //Gets the 2nd digit.
long y = 1; //gets the first.
long sum1 = 0; //Holds the doubled sum.
long sum2 = 0; //Holds the undoubled sum.
int n = 8;
while (n > 0)
{
long cc1 = ccnumber / y;
cc1 = cc1 % 10;
long cc2 = ccnumber / x;
cc2 = cc2 % 10;
y = y * 100;
x = x * 100;
// Times CC2 by 2.
cc2 = cc2 * 2;
// Check if double digit then mine by 9, as to add the two digits together.
if (cc2 / 10 != 0)
{
cc2 = cc2 - 9;
}
sum1 = sum1 + cc2;
sum2 = sum2 + cc1;
printf("%d, %ld, %ld, %ld, %ld\n",n,cc2,cc1,x,y);
}
}
What you'll see is that x and y are eventually overloaded and reset to 0, which will cause division by 0 with associated fp error and core dump.
$ ./a.out
Number: 5
8, 0, 5, 1000, 100
8, 0, 0, 100000, 10000
8, 0, 0, 10000000, 1000000
8, 0, 0, 1000000000, 100000000
8, 0, 0, 100000000000, 10000000000
8, 0, 0, 10000000000000, 1000000000000
8, 0, 0, 1000000000000000, 100000000000000
8, 0, 0, 100000000000000000, 10000000000000000
8, 0, 0, -8446744073709551616, 1000000000000000000
8, 0, 0, 3875820019684212736, 7766279631452241920
8, 0, 0, 200376420520689664, 1864712049423024128
8, 0, 0, 1590897978359414784, 2003764205206896640
8, 0, 0, -6930898827444486144, -2537764290115403776
8, 0, 0, 7886392056514347008, 4477988020393345024
8, 0, 0, -4570789518076018688, 5076944270305263616
8, 0, 0, 4089650035136921600, -8814407033341083648
8, 0, 0, 3136633892082024448, 4003012203950112768
8, 0, 0, 68739955140067328, -5527149226598858752
8, 0, 0, 6873995514006732800, 687399551400673280
8, 0, 0, 4870020673419870208, -5047021154770878464
8, 0, 0, 7386721425538678784, -6640025486929952768
8, 0, 0, 802379605485813760, 80237960548581376
8, 0, 0, 6450984253743169536, 8023796054858137600
8, 0, 0, -537617205517352960, 9169610316303040512
8, 0, 0, 1578511669393358848, -5376172055173529600
8, 0, 0, -8169529724050079744, -2661627379775963136
8, 0, 0, -5296233161787703296, -7908320945662590976
8, 0, 0, 5332261958806667264, 2377900603251621888
8, 0, 0, -1729382256910270464, -2017612633061982208
8, 0, 0, -6917529027641081856, 1152921504606846976
8, 0, 0, -9223372036854775808, 4611686018427387904
8, 0, 0, 0, 0
Floating point exception (core dumped)
Related
If I have a number (long), how can I split its digits into an array?
Example: 4003607001000014 -> [4, 0, 0, 3, 6, 0, 7, 0, 0, 1, 0, 0, 0, 0, 1, 4].
I tried using modulo (n % (10 * i)), where i starts at 1 and its value increases by a multiple of 10 each iteration of a for loop. Then adding the result to the array from n to 0, but this way, any zeros are ignored.
Try dividing the number by 10 each iteration, this is more straightforward than modulo by increasing powers of 10:
unsigned char digits[BIG_ENOUGH];
unsigned long number;
unsigned i = 0;
while (number) {
digits[i++] = number%10;
number /= 10;
}
If you need digits[0] to store the most significant digit instead of the least significant digit, reverse the array afterwards:
for (unsigned low = 0, high = digits-1; low < high; low++, high--) {
unsigned char tmp = digits[low];
digits[low] = digits[high];
digits[high] = tmp;
}
Problem
Consider the sequence D of the last decimal digits of the first N Fibonacci numbers, i.e. D = (F0%10,F1%10,…,FN−1%10).
Now, you should perform the following process:
Let D=(D1,D2,…,Dl)
If l=1, the process ends.
Create a new sequence
E=(D2,D4,…,D2⌊l/2⌋)
In other words, E is the sequence created by removing all odd-indexed elements from D
Change D to E
When this process terminates, the sequence D
contains only one number. You have to find this number.
Input
The first line of the input contains a single integer T
denoting the number of test cases.
The description of T test cases follows.
The first and only line of each test case contains a single integer N
Output
For each test case, print a single line containing one integer ― the last remaining number.
Code
#include <stdio.h>
#include <stdlib.h>
int test(int *arr, int n);
int main() {
int t;
scanf("%d", &t);
while (t--) {
int n;
scanf("%d", &n);
int *arr;
arr = (int *)malloc((n + 1) * sizeof(int));
arr[1] = 0;
arr[2] = 1;
for (int i = 3; i <= n; i++) {
arr[i] = arr[i - 1] + arr[i - 2];
}
/*
for(int k=1;k<=n;k++){
printf("%d ",arr[k] );
}
printf("\n");
*/
printf("%d\n", (test(arr, n)) % 10);
}
}
int test(int *arr, int n) {
if (n == 1) {
return arr[1];
} else {
for (int i = 1; i <= (n / 2); i++) {
arr[i] = arr[2 * i];
}
return test(arr, n / 2);
}
}
Using the algorithm from https://math.stackexchange.com/questions/681674/recursively-deleting-every-second-element-in-a-list,
Find the largest integer A, such that 2^A < N.
Find Fibonnaci(2^A - 1) % 10
Adding to Bill Lynch's answer, which is itself based on this other answer by happymath:
You will always end up getting 2n − 1 where n is maximum integer such that 2n < K
I'd like to point out another useful mathematical property.
In number theory, the nth Pisano period, written π(n), is the period with which the sequence of Fibonacci numbers taken modulo n repeats.
(https://en.wikipedia.org/wiki/Pisano_period)
Here we need to consider the case where n = 10, π(10) = 60 and the last decimal digits correspond to the OEIS sequence A003893:
0, 1, 1, 2, 3, 5, 8, 3, 1, 4, 5, 9, 4, 3, 7, 0, 7, 7, 4, 1, 5, 6, 1, 7, 8, 5, 3, 8, 1, 9, 0, 9, 9, 8, 7, 5, 2, 7, 9, 6, 5, 1, 6, 7, 3, 0, 3, 3, 6, 9, 5, 4, 9, 3, 2, 5, 7, 2, 9, 1
So that there's no need to calculate the actual Fibonacci number, nor to generate all the sequence up to N.
I have written code for dynamic programming, matrix chain multiplication algorithm. For this question, I am not concerned with the implementation details of algorithm.
I am trying to debug it using gdb. However, I am having a hard time examining cost_table 2-D array inside matrix_chain_order function.
Inside matrix_chain_order function, I set a breakpoint and examine the cost_table 2-D array. I have also used printf statements there.
The printf statements print the correct value of a cell in cost_table.
I found some revelant information in this SO QA: how to print 2d arry values in gdb.
I did not understand what the answer really explained. But it gave me a direction, so I tried printing cost_table and its cell values in gdb. (Session below)
Code:
/* MATRIX-CHAIN-MULTIPLICATION - CLRS 3rd Edition, Chapter 15 */
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
#define array_length(arr) (sizeof(arr) == 0 ? 0 : sizeof(arr) / sizeof((arr)[0]));
/* define input sequence to matrix_chain_order function */
const int INPUT_SEQUENCE[] = {4, 10, 3, 12, 20};
/* DEFINE m[i, j]:
* Let m[i, j] be the minimum number of scalar multiplications needed to compute
* matrix A_suffix_i..j; for the full problem, the lowest cost way to compute A_suffix_1..n
* would thus be m[1, n].
*/
/* The function computes the rows from bottom to top and from left to right within
* each row.
* It computes each entry m[i, j] using products p_suffix_i-1 * p_suffix_k * p_suffix_j
* for k = i, i + 1, ...., j - 1 and all entries southwest and southeast from m[i, j].
*
* This prodedure assumes that matrix A_suffix_i has dimensions p_suffix_i-1 * p_suffix_i
* for i = 1, 2, ...., n.
* Its input is a sequence p = <p_suffix_0, p_suffix_1, ...., p_suffix_n>, where
* p.length = n + 1.
*
* The procedure uses an auxiliary table m[1 ..n, 1 ..n] for storing the m[i, j] costs,
* and another auxiliary table s[1 ..n - 1, 2 ..] that records which index of k achieved
* the optimal cost in computing m[i, j].
*/
void matrix_chain_order (int ct_rows, int ct_cols, int cost_table[ct_rows][ct_cols], int kit_rows, int kit_cols, int k_idx_table[kit_rows][kit_cols]);
int main ()
{
int sequence_len = array_length(INPUT_SEQUENCE);
/* initialize table (2-D array), m[1 ..n, 1..n] */
int m = 0, n = 0;
int cost_table[sequence_len][sequence_len];
for (m = 0; m < sequence_len; m++) {
for (n = 0; n < sequence_len; n++) {
/* m[i, i] = 0, for i = 1, 2, ...., n (the minimum costs for chains of length 1) */
if (n == m) {
cost_table[m][n] = 0;
} else {
cost_table[m][n] = INT_MAX;
}
}
}
/* initialize table (2-D array), s[1 ..n - 1, 2..n] */
int o = 0, p = 0;
int k_idx_table[sequence_len - 1][sequence_len - 1];
for (o = 0; o < sequence_len - 1; o++) {
for (p = 0; p < sequence_len - 1; p++) {
k_idx_table[o][p] = -1;
}
}
matrix_chain_order(sequence_len, sequence_len, cost_table, sequence_len, sequence_len - 1, k_idx_table);
return 0;
}
/* NOTE on array passed to the function. */
/* When you pass an array to a function, it decays into a pointer to the first element,
* at which point knowledge of its size is lost. You need to work it out before decay
* and pass that information with the array.
*/
void matrix_chain_order(int ct_rows, int ct_cols, int cost_table[ct_rows][ct_cols], int kit_rows, int kit_cols, int k_idx_table[kit_rows][kit_cols])
{
int sequence_len = array_length(INPUT_SEQUENCE);
/* use recurrence,
*
* min[i, j] = 0 , if i = j
* min[i, j] = min {m[i, k] + m[k + 1, j] + p_suffix_i-1 * p_suffix_k * p_suffix_j , if i < j
*
* to compute m[i, i + 1] for i = 1, 2, ...., n - 1 (the minimum costs of chains of length l = 2)
* during the first execution of the for loop.
* The second time through the loop, it computes m[i, i + 2] for i = 1, 2, ...., n - 2
* (the minimum costs for chains of length l = 3), and so forth.
*/
int chain_len = 0, i = 1, j = 0, k = 0, cost = INT_MAX;
for (chain_len = 2; chain_len <= sequence_len; chain_len++) {
for (i = 1; i <= sequence_len - chain_len + 1; i++) {
j = i + chain_len - 1;
for (k = i; k <= j - 1; k++) {
/* at each step, the m[i, j] cost computed depends only on table entries m[i, k] and m[k + 1, j]
* already computed
*/
printf("Printed cost_table[%d][%d] : %d\n", i, k, cost_table[i][k]);
printf("Printed cost_table[%d][%d] : %d\n", (k+1), j, cost_table[k+1][j]);
cost = cost_table[i][k] + cost_table[k + 1][j] + INPUT_SEQUENCE[i - 1] * INPUT_SEQUENCE[k] * INPUT_SEQUENCE[j];
if (cost < cost_table[i][j]) {
cost_table[i][j] = cost;
k_idx_table[i][j] = k;
}
}
}
}
}
gdb session:
(gdb) p ((int (*) [5][5]) cost_table)[1][1]
$3 = {0, 0, 65280, 0, -8944}
(gdb) p (int [][5]) *cost_table
$4 = 0x7fffffffdca0
(gdb) p (int [5][5]) *cost_table
Invalid cast.
(gdb) p (int [][5]) **cost_table
warning: array element type size does not divide object size in cast
$5 = 0x7fffffffdca0
(gdb) p (int [][5]) *cost_table
$6 = 0x7fffffffdca0
(gdb) p (int [][5]) cost_table
warning: array element type size does not divide object size in cast
$7 = 0x7fffffffdbe0
(gdb) p cost_table#5#5
$16 = {{0x7fffffffdca0, 0x500000005, 0x26, 0x100000002, 0x500000001}, {0x7fffffff00000002, 0x4, 0x3, 0x1f7ffe728, 0x7fffffffdca0}, {0x0, 0x5, 0x7fffffffddf0, 0x400952 <main+892>, 0xffffffffffffffff}, {
0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff}, {0xffffffffffffffff, 0xffffffffffffffff, 0x0, 0x7fffffffde10, 0x7fffffff00000000}}
(gdb) p *cost_table#5#5
$17 = {{{0, 2147483647, 2147483647, 2147483647, 2147483647}, {2147483647, 0, 2147483647, 2147483647, 2147483647}, {2147483647, 2147483647, 0, 2147483647, 2147483647}, {2147483647, 2147483647,
2147483647, 0, 2147483647}, {2147483647, 2147483647, 2147483647, 2147483647, 0}}, {{0, -140389360, 32767, 4, 0}, {0, 0, 65280, 0, -8944}, {32767, 4, 0, 0, 0}, {4, 0, 0, 0, 4}, {0, 0, 0, 4, 0}}, {{
0, 0, 0, 5, 5}, {4, 4, 5, 4, 0}, {4, 0, -9056, 32767, 3}, {0, 3, 0, -9136, 32767}, {1781326592, 1051810453, 0, 0, 0}}, {{0, 4195552, 0, -8496, 32767}, {0, 0, 0, 0, 4197632}, {0, -140322768, 32767,
0, 0}, {-8488, 32767, 0, 1, 4195798}, {0, 0, 0, 1661416990, 1731120}}, {{4195552, 0, -8496, 32767, 0}, {0, 0, 0, -989383138, -1731249}, {-690538978, -1735179, 0, 0, 0}, {0, 0, 0, 1, 0}, {4195798,
0, 4197744, 0, 0}}}
(gdb) p **cost_table#5#5
$18 = {{0, 2147483647, 2147483647, 2147483647, 2147483647}, {2147483647, 0, 2147483647, 2147483647, 2147483647}, {2147483647, 2147483647, 0, 2147483647, 2147483647}, {2147483647, 2147483647, 2147483647,
0, 2147483647}, {2147483647, 2147483647, 2147483647, 2147483647, 0}}
(gdb) p cost_table[i][k]
Cannot perform pointer math on incomplete types, try casting to a known type, or void *.
I don't get how the commands that I have used in gdb session result in their respective outputs.
Why am I unable to use p cost_table[i][k] directly in gdb,
whereas the printf statements print the result in execution of
code?
p ((int (*) [5][5]) cost_table)[1][1]: What happens if I change
value of numbers in this command or if I do something like
p ((int(*) [][5]) cost_table)[1][1]?
Why is the output of p *cost_table#5#5 and p **cost_table#5#5 so
different?
My requirement is to be able to examine the cost_table and its cells in gdb.
Any other suggestions is welcomed.
Just ask gbd for it :)
Breakpoint 2, matrix_chain_order (ct_rows=5, ct_cols=5, cost_table=0x7fffffffdac0, kit_rows=5, kit_cols=4, k_idx_table=0x7fffffffda80) at delme.c:96
96 printf("Printed cost_table[%d][%d] : %d\n", (k+1), j, cost_table[k+1][j]);
(gdb) ptype cost_table
type = int (*)[5]
(gdb) p ((int (*) [5])cost_table)[i][j]
$12 = 2147483647
You may also go up one frame ('up' in gdb) and print directly cost_table[idx1][idx2] but it is probably less user friendly to debug in the loop...
the type gdb gives (int(*)[5]) stand for pointer to array 5 of int (see
https://cdecl.org/?q=int+%28*t%29%5B5%5D if you want to experience the syntax.)
The array type decays that's why only a pointer remains; you may have a look to Manipulate multidimensional array in a function for more explanation in C.
Using a microcontroller (PIC18F4580), I need to collect data and send it to an SD card for later analysis. The data it collects will have values between 0 and 1023, or 0x0 and 0x3FF.
So what I need to do is convert 1023 into a base 10 string of literal ASCII values (0x31, 0x30, 0x32, 0x33, ...).
My problem is that the only way I can think of to split the digits apart requires a lot of division.
char temp[4];
temp[0] = 1023 % 10;
temp[1] = (1023 % 100) / 10;
temp[2] = (1023 % 1000) / 100;
temp[3] = (1023 % 10000) / 1000;
Using this method, finding the ASCII values of an n digit decimal number requires 2n-1 divisions. Is there a method that would be faster?
The end goal of this is to wind up with a .csv file on the SD card that can quickly be plugged into any laptop to see a graph of the data in Excel.
The obvious solution is not to convert the data to ASCII at all but store it in binary format. That way all you need to worry about is the endianness of the data. If the system performing the later analysis is far more powerful than your embedded target, then it would make sense to let that deal with the conversion and and byte order.
On the other hand, it is possible that the execution time of the / and % is insignificant compared to the time taken to transfer the data to the SD card; so make sure that you are optimising the right thing.
There's certainly a much faster way: have an array of 1024 pre-computed strings. Then you can just do bounds checking, followed by an index into the array.
It's unclear from your question whether your code is running on the microcontroller though. If that's the case, you may not have enough memory for this approach.
I agree with what Clifford said, that you shouldn't worry about optimizing it if you don't have to, and that you can push the log cleanup to your analysis platform, rather than worrying about formatting in an embedded application.
That being said, here's an article that might be useful to you. It uses a loop, shifts, additions and branches, with linear/constant complexity: http://www.johnloomis.org/ece314/notes/devices/binary_to_BCD/bin_to_bcd.html
Also, I thought it would be fun to make some code that doesn't perform any divides, multiplies, or branches, but still gives the correct answer [0 - 1024). No promises that this is any faster than other options. This sort of code is just an option to explore.
I'd love to see if anyone can provide some tricks to make the code smaller, require less memory, or require fewer operations, while keeping the rest of the counts equal, or shrinking them :)
Stats:
224 bytes in constants (no idea on the code size)
5 bit-shift-rights
3 subtracts
5 bitwise-ands
4 bitwise-ors
1 greater-than comparison
Perf:
Using the perf comparisons and itoa routines in Jonathan Leffler's answer, here are the stats I got:
Division 2.15
Subtraction 4.87
My solution 1.56
Brute force lookup 0.36
I increased the iteration count to 200000 to ensure I didn't have any problems with timing resolution, and had to add volatile to the function signatures so that the compiler didn't optimize out the loop. I used VS2010 express w/ vanilla "release" settings, on a 3ghz dual core 64 bit Windows 7 machine (tho it compiled to 32 bit).
The code:
#include "stdlib.h"
#include "stdio.h"
#include "assert.h"
void itoa_ten_bits(int n, char s[])
{
static const short thousands_digit_subtract_map[2] =
{
0, 1000,
};
static const char hundreds_digit_map[128] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
0, 0, 0,
};
static const short hundreds_digit_subtract_map[10] =
{
0, 100, 200, 300, 400, 500, 600, 700, 800, 900,
};
static const char tens_digit_map[12] =
{
0, 1, 2, 3, 3, 4, 5, 6, 7, 7, 8, 9,
};
static const char ones_digit_map[44] =
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
0, 1, 2, 3
};
/* Compiler should optimize out appX constants, % operations, and + operations */
/* If not, use this:
static const char ones_digit_append_map[16] =
{
0, 6, 2, 8, 4, 10, 6, 12, 8, 14, 10, 16, 12, 18, 14, 20,
};
*/
static const char a1 = 0x10 % 10, a2 = 0x20 % 10, a3 = 0x40 % 10, a4 = 0x80 % 10;
static const char ones_digit_append_map[16] =
{
0, a1, a2, a1 + a2,
a3, a1 + a3, a2 + a3, a1 + a2 + a3,
a4, a1 + a4, a2 + a4, a1 + a2 + a4,
a3 + a4, a1 + a3 + a4, a2 + a3 + a4, a1 + a2 + a3 + a4,
};
char thousands_digit, hundreds_digit, tens_digit, ones_digit;
assert(n >= 0 && n < 1024 && "n must be between [0, 1024)");
/* n &= 0x3ff; can use this instead of the assert */
thousands_digit = (n >> 3 & 0x7f) > 0x7c;
n -= thousands_digit_subtract_map[thousands_digit];
ones_digit = ones_digit_map[
(n & 0xf)
+ ones_digit_append_map[n >> 4 & 0xf]
+ ones_digit_append_map[n >> 8 & 0x3]
];
n -= ones_digit;
hundreds_digit = hundreds_digit_map[n >> 3 & 0x7f];
n -= hundreds_digit_subtract_map[hundreds_digit];
tens_digit = tens_digit_map[n >> 3];
s[0] = '0' | thousands_digit;
s[1] = '0' | hundreds_digit;
s[2] = '0' | tens_digit;
s[3] = '0' | ones_digit;
s[4] = '\0';
}
int main(int argc, char* argv)
{
int i;
for(i = 0; i < 1024; ++i)
{
char blah[5];
itoa_ten_bits(i, blah);
if(atoi(blah) != i)
printf("failed %d %s\n", i, blah);
}
}
There's a way of doing it using subtractions, but I am not convinced it's faster than using subtractions and modulus on a "normal" CPU (may be different in an embedded environment).
Something like this:
char makedigit (int *number, int base)
{
static char map[] = "0123456789";
int ix;
for (ix=0; *number >= base; ix++) { *number -= base; }
return map[ix];
}
char *makestring (int number)
{
static char tmp[5];
tmp[0] = makedigit(&number, 1000);
tmp[1] = makedigit(&number, 100);
tmp[2] = makedigit(&number, 10);
tmp[3] = makedigit(&number, 1);
tmp[4] = '\0';
return tmp;
}
Then, a call to makestring() should result in a (static, so copy it before overwriting) string with the converted number (zero-prefixed, at 4 characters width, as the original assumption is a value in the 0-1023 range).
With some care in finding the right number(s) to use, you can multiply by the reciprocal of the base rather than dividing by the base. Terje's code is for an x86, but porting the general idea to a PIC shouldn't be tremendously difficult.
If the values are correctly in range (0..1023), then your last conversion is unnecessarily wasteful on the divisions; the last line could be replaced with:
temp[3] = 1023 / 1000;
or even:
temp[3] = 1023 >= 1000;
Since division is repeated subtraction, but you have a very special case (not a general case) division to deal with, I'd be tempted to compare the timings for the following code with the division version. I note that you put the digits into the string in 'reverse order' - the least significant digit goes in temp[0] and the most in temp[4]. Also, there is no chance of null-terminating the string given the storage. This code uses a table of 8 bytes of static data - considerably less than many of the other solutions.
void convert_to_ascii(int value, char *temp)
{
static const short subtractors[] = { 1000, 100, 10, 1 };
int i;
for (i = 0; i < 4; i++)
{
int n = 0;
while (value >= subtractors[i])
{
n++;
value -= subtractors[i];
}
temp[3-i] = n + '0';
}
}
Performance testing - Intel x86_64 Core 2 Duo 3.06 GHz (MacOS X 10.6.4)
This platform is probably not representative of your microcontroller, but the test shows that on this platform, the subtraction is considerably slower than the division.
void convert_by_division(int value, char *temp)
{
temp[0] = (value % 10) + '0';
temp[1] = (value % 100) / 10 + '0';
temp[2] = (value % 1000) / 100 + '0';
temp[3] = (value % 10000) / 1000 + '0';
}
void convert_by_subtraction(int value, char *temp)
{
static const short subtractors[] = { 1000, 100, 10, 1 };
int i;
for (i = 0; i < 4; i++)
{
int n = 0;
while (value >= subtractors[i])
{
n++;
value -= subtractors[i];
}
temp[3-i] = n + '0';
}
}
#include <stdio.h>
#include <timer.h>
#include <string.h>
static void time_convertor(const char *tag, void (*function)(void))
{
int r;
Clock ck;
char buffer[32];
clk_init(&ck);
clk_start(&ck);
for (r = 0; r < 10000; r++)
(*function)();
clk_stop(&ck);
printf("%s: %12s\n", tag, clk_elapsed_us(&ck, buffer, sizeof(buffer)));
}
static void using_subtraction(void)
{
int i;
for (i = 0; i < 1024; i++)
{
char temp1[4];
convert_by_subtraction(i, temp1);
}
}
static void using_division(void)
{
int i;
for (i = 0; i < 1024; i++)
{
char temp1[4];
convert_by_division(i, temp1);
}
}
int main()
{
int i;
for (i = 0; i < 1024; i++)
{
char temp1[4];
char temp2[4];
convert_by_subtraction(i, temp1);
convert_by_division(i, temp2);
if (memcmp(temp1, temp2, 4) != 0)
printf("!!DIFFERENCE!! ");
printf("%4d: %.4s %.4s\n", i, temp1, temp2);
}
time_convertor("Using division ", using_division);
time_convertor("Using subtraction", using_subtraction);
time_convertor("Using division ", using_division);
time_convertor("Using subtraction", using_subtraction);
time_convertor("Using division ", using_division);
time_convertor("Using subtraction", using_subtraction);
time_convertor("Using division ", using_division);
time_convertor("Using subtraction", using_subtraction);
return 0;
}
Compiling with GCC 4.5.1, and working in 32-bit, the average timings were (optimization '-O'):
0.13 seconds using division
0.65 seconds using subtraction
Compiling and working in 64-bit, the average timings were:
0.13 seconds using division
0.48 seconds using subtraction
Clearly, on this machine, using subtraction is not a winning proposition. You would have to measure on your machine to make a decision. And removing the modulo 10000 operation will only skew results in favour of the division (it knocks about 0.02 seconds off the time with division when replaced with the comparison; that's a 15% saving and worth having).
Is there some reason that you're particularly concerned about this?
If your compiler and C library provide an itoa() function, use that, and then worry about writing this code (and associated tests and so forth to make sure you got it right!) if for some reason that turns out to be too slow or doesn't fit into RAM or something.
I've replaced my previous answer with a better one. This code creates a 4-character string in the proper order, most significant digit in output[0] to least significant in output[3] with a zero terminator in output[4]. I don't know anything about your PIC controller or C compiler, but this code doesn't require anything more than 16-bit integers, addition/subtraction, and shifting.
int x;
char output[5];
output[4] = 0;
x = 1023;
output[3] = '0' + DivideByTenReturnRemainder(&x);
output[2] = '0' + DivideByTenReturnRemainder(&x);
output[1] = '0' + DivideByTenReturnRemainder(&x);
output[0] = '0' + x;
The key to this is the magical function DivideByTenReturnRemainder. Without using division explicitly it's still possible to divide by powers of 2 by shifting right; the problem is that 10 isn't a power of 2. I've sidestepped that problem by multiplying the value by 25.625 before dividing by 256, letting integer truncation round down to the proper value. Why 25.625? Because it's easily represented by powers of 2. 25.625 = 16 + 8 + 1 + 1/2 + 1/8. Again, multiplying by 1/2 is the same as shifting right one bit, and multiplying by 1/8 is shifting right by 3 bits. To get the remainder, multiply the result by 10 (8+2) and subtract it from the original value.
int DivideByTenReturnRemainder(int * p)
{
/* This code has been tested for an input range of 0 to 1023. */
int x;
x = *p;
*p = ((x << 4) + (x << 3) + x + (x >> 1) + (x >> 3)) >> 8;
return x - ((*p << 3) + (*p << 1));
}
Are you required to use an ASCII string of the decimal representation? It would be much easier to store it in hexadecimal format. No division required, only (relatively cheap) shift operations. Excel should be able to read it if you prepend a '0x' to each number.
Let's say I have an integer called 'score', that looks like this:
int score = 1529587;
Now what I want to do is get each digit 1, 5, 2, 9, 5, 8, 7 from the score using bitwise operators(See below edit note).
I'm pretty sure this can be done since I've once used a similar method to extract the red green and blue values from a hexadecimal colour value.
How would I do this?
Edit
It doesn't necessarily have to be bitwise operators, I just thought it'd be simpler that way.
You use the modulo operator:
while(score)
{
printf("%d\n", score % 10);
score /= 10;
}
Note that this will give you the digits in reverse order (i.e. least significant digit first). If you want the most significant digit first, you'll have to store the digits in an array, then read them out in reverse order.
RGB values fall nicely on bit boundaries; decimal digits don't. I don't think there's an easy way to do this using bitwise operators at all. You'd need to use decimal operators like modulo 10 (% 10).
Agree with previous answers.
A little correction: There's a better way to print the decimal digits from left to right, without allocating extra buffer. In addition you may want to display a zero characeter if the score is 0 (the loop suggested in the previous answers won't print anythng).
This demands an additional pass:
int div;
for (div = 1; div <= score; div *= 10)
;
do
{
div /= 10;
printf("%d\n", score / div);
score %= div;
} while (score);
Don't reinvent the wheel. C has sprintf for a reason.
Since your variable is called score, I'm guessing this is for a game where you're planning to use the individual digits of the score to display the numeral glyphs as images. In this case, sprintf has convenient format modifiers that will let you zero-pad, space-pad, etc. the score to a fixed width, which you may want to use.
This solution gives correct results over the entire range [0,UINT_MAX]
without requiring digits to be buffered.
It also works for wider types or signed types (with positive values) with appropriate type changes.
This kind of approach is particularly useful on tiny environments (e.g. Arduino bootloader) because it doesn't end up pulling in all the printf() bloat (when printf() isn't used for demo output) and uses very little RAM. You can get a look at value just by blinking a single led :)
#include <limits.h>
#include <stdio.h>
int
main (void)
{
unsigned int score = 42; // Works for score in [0, UINT_MAX]
printf ("score via printf: %u\n", score); // For validation
printf ("score digit by digit: ");
unsigned int div = 1;
unsigned int digit_count = 1;
while ( div <= score / 10 ) {
digit_count++;
div *= 10;
}
while ( digit_count > 0 ) {
printf ("%d", score / div);
score %= div;
div /= 10;
digit_count--;
}
printf ("\n");
return 0;
}
Usually, this problem resolve with using the modulo of a number in a loop or convert a number to a string. For convert a number to a string, you may can use the function itoa, so considering the variant with the modulo of a number in a loop.
Content of a file get_digits.c
$ cat get_digits.c
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
// return a length of integer
unsigned long int get_number_count_digits(long int number);
// get digits from an integer number into an array
int number_get_digits(long int number, int **digits, unsigned int *len);
// for demo features
void demo_number_get_digits(long int number);
int
main()
{
demo_number_get_digits(-9999999999999);
demo_number_get_digits(-10000000000);
demo_number_get_digits(-1000);
demo_number_get_digits(-9);
demo_number_get_digits(0);
demo_number_get_digits(9);
demo_number_get_digits(1000);
demo_number_get_digits(10000000000);
demo_number_get_digits(9999999999999);
return EXIT_SUCCESS;
}
unsigned long int
get_number_count_digits(long int number)
{
if (number < 0)
number = llabs(number);
else if (number == 0)
return 1;
if (number < 999999999999997)
return floor(log10(number)) + 1;
unsigned long int count = 0;
while (number > 0) {
++count;
number /= 10;
}
return count;
}
int
number_get_digits(long int number, int **digits, unsigned int *len)
{
number = labs(number);
// termination count digits and size of a array as well as
*len = get_number_count_digits(number);
*digits = realloc(*digits, *len * sizeof(int));
// fill up the array
unsigned int index = 0;
while (number > 0) {
(*digits)[index] = (int)(number % 10);
number /= 10;
++index;
}
// reverse the array
unsigned long int i = 0, half_len = (*len / 2);
int swap;
while (i < half_len) {
swap = (*digits)[i];
(*digits)[i] = (*digits)[*len - i - 1];
(*digits)[*len - i - 1] = swap;
++i;
}
return 0;
}
void
demo_number_get_digits(long int number)
{
int *digits;
unsigned int len;
digits = malloc(sizeof(int));
number_get_digits(number, &digits, &len);
printf("%ld --> [", number);
for (unsigned int i = 0; i < len; ++i) {
if (i == len - 1)
printf("%d", digits[i]);
else
printf("%d, ", digits[i]);
}
printf("]\n");
free(digits);
}
Demo with the GNU GCC
$~/Downloads/temp$ cc -Wall -Wextra -std=c11 -o run get_digits.c -lm
$~/Downloads/temp$ ./run
-9999999999999 --> [9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9]
-10000000000 --> [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
-1000 --> [1, 0, 0, 0]
-9 --> [9]
0 --> [0]
9 --> [9]
1000 --> [1, 0, 0, 0]
10000000000 --> [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
9999999999999 --> [9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9]
Demo with the LLVM/Clang
$~/Downloads/temp$ rm run
$~/Downloads/temp$ clang -std=c11 -Wall -Wextra get_digits.c -o run -lm
setivolkylany$~/Downloads/temp$ ./run
-9999999999999 --> [9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9]
-10000000000 --> [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
-1000 --> [1, 0, 0, 0]
-9 --> [9]
0 --> [0]
9 --> [9]
1000 --> [1, 0, 0, 0]
10000000000 --> [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
9999999999999 --> [9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9]
Testing environment
$~/Downloads/temp$ cc --version | head -n 1
cc (Debian 4.9.2-10) 4.9.2
$~/Downloads/temp$ clang --version
Debian clang version 3.5.0-10 (tags/RELEASE_350/final) (based on LLVM 3.5.0)
Target: x86_64-pc-linux-gnu
Thread model: posix
#include<stdio.h>
int main() {
int num; //given integer
int reminder;
int rev=0; //To reverse the given integer
int count=1;
printf("Enter the integer:");
scanf("%i",&num);
/*First while loop will reverse the number*/
while(num!=0)
{
reminder=num%10;
rev=rev*10+reminder;
num/=10;
}
/*Second while loop will give the number from left to right*/
while(rev!=0)
{
reminder=rev%10;
printf("The %d digit is %d\n",count, reminder);
rev/=10;
count++; //to give the number from left to right
}
return (EXIT_SUCCESS);}
First convert your integer to a string using sprintf, then do whatever you want with its elements, that are chars. Assuming an unsigned score:
unsigned int score = 1529587, i;
char stringScore [11] = { 0 };
sprintf( stringScore, "%d, score );
for( i=0; i<strlen(stringScore); i++ )
printf( "%c\n", stringScore[i] );
Please note how:
It prints digits starting from the most significant one
stringScore is 11 characters long assuming that the size of int, in your platform, is 4 bytes, so that the maximum integer is 10 digits long. The eleventh one is for the string terminator character '\0'.
sprintf makes all the work for you
Do you need to have an integer for every single digit?
Since we are sure that stringScore contains only digits, the conversion is really easy. If dig is the character containing the digit, the corresponding integer can be obtained in this way:
int intDigit = dig - '0';
//this can be easily understandable for beginners
int score=12344534;
int div;
for (div = 1; div <= score; div *= 10)
{
}
/*for (div = 1; div <= score; div *= 10); for loop with semicolon or empty body is same*/
while(div>1)
{
div /= 10;
printf("%d\n`enter code here`", score / div);
score %= div;
}
I've made this solution, it-s simple instead read an integer, i read a string (char array in C), then write with a for bucle, the code also write the sum of digits
// #include<string.h>
scanf("%s", n);
int total = 0;
for (int i = 0; i< strlen(n); i++){
printf("%c", n[i]);
total += (int)(n[i]) -48;
}
printf("%d", total);