3

In this answer, I made a function to convert an integer to an ASCII string:

void writeInteger(unsigned int input) {
    unsigned int start = 1;
    unsigned int counter;
    while (start <= input)
        start *= 10;
    for (counter = start / 10; counter >= 1; counter /= 10)
        serialWrite(((input / counter) % 10) + 0x30);
}

I tested this function with a loop:

unsigned int counter;
for (counter = 0; counter< 1000000; counter++) {
    writeInteger(counter);
    serialWrite('\r');
    serialWrite('\n');
}

This works, for \$1\le{}n\le9999\$. However, for 10,000 and above, I'm getting weird strings on the terminal:

10000 => 2943
10001 => 2943
10002 => 2944
10003 => 2944
10004 => 2944
10005 => 2945
...

Why is that? How can I fix it?

  • 1
    Check this answer: http://stackoverflow.com/questions/6302195/where-can-i-find-a-free-or-open-source-c-library-to-do-bcd-math#6302328 You really want to limit your divisions to the minimum, as they are *slowwwwwwwwwwww* – jippie Apr 13 '13 at 07:22
  • You have made `counter<1,000,0000` in the main. However, counter is an `int` – abdullah kahraman Apr 13 '13 at 07:24
  • @abdullahkahraman yeah, thanks - I thought an `int` would hold 32 bits, as in Java, for example. –  Apr 13 '13 at 07:25
  • [Here](http://pastebin.com/sekqTh3n) is my routine that is optimized for an 8-bit microcontroller. It is fast since it does not use any modulus or multiplication. Also, you can modify it easily so that it is suitable for more digits. – abdullah kahraman Apr 13 '13 at 07:34

1 Answers1

4

It's because the following section of code will be trying to set start to 100,000 for numbers equal to or above 10,000 which is too big for an unsigned int which is a 16-bit and can only hold 0-65535:

while (start <= input)
    start *= 10;

Changing the definition to the following should fix it:

unsigned long start = 1;

Another alternative to make the code clearer is to include stdint.h so it may be defined as the following that will work across compilers:

#include <stdint.h>
uint32_t start = 1;
PeterJ
  • 17,131
  • 37
  • 56
  • 91
  • How come? When `input` is 10,000 , it will set `start` to 10,000. – abdullah kahraman Apr 13 '13 at 07:23
  • Ahh! I thought an int would hold 32 bits, but that's a `long`! For reference, [section 2.1](http://ww1.microchip.com/downloads/en/devicedoc/51288f.pdf). –  Apr 13 '13 at 07:24
  • @abdullahkahraman no, it sets it to 100,000 and the _counter_ is set to start/10. –  Apr 13 '13 at 07:24
  • When input is 10,000, it will set `start` to 10,000. However, when the input is bigger than 10,000 it will set `start` to 100,000. What am I doing wrong? – abdullah kahraman Apr 13 '13 at 07:26
  • @abdullahkahraman It's `<=`, not `<` ;) –  Apr 13 '13 at 07:27
  • @CamilStaps, can be a trap with some micro compilers, I've also added the way I'd normally go about it that's more portable. – PeterJ Apr 13 '13 at 07:27
  • @CamilStaps But 10,000 = 10,000 when `input=10,000`. – abdullah kahraman Apr 13 '13 at 07:28
  • @abdullahkahraman as long as `start<=10,000`, it will be multiplied by 10. The last time it multiplies by 10 is when `start=10,000`, so the end result would be 100,000. –  Apr 13 '13 at 07:30