More elegant digit isolation from multiple-digit number?

Hey,

beginner here.

The good news: My code is working fine. My question is only about how to streamline it.

I want to isolate the digits from a multiple-digit number. So far, I do it like this:

long C = [number with many digits here];
int D1 = C / 100000000 % 10;
int D2 = C / 10000000 % 10;
.
.
.
int DY = C / 10 % 10;
int DZ = C % 10;

While this works, I don't think it is very efficient. The huge divisions have to be done all over again. It should be much more efficient to start from the end, i.e. remember the result for the first division by 10, then in the next step divide that result by 10 again and so on. The dividend would become gradually smaller, and the divisor would be smaller, too (10). Any suggestions on how to implement all this most elegant/abstract/intelligent?

What do you want, efficiency (speed and/or compiled code size) or elegance (readability, conciseness, maintainability etc.)? Usually there is some trade off, it's unusual to target both at the same time.

Have you tried coding the method that you describe?

if your concerned about the complexity of a division by a constant, you can easily do the same with multiplication -- multiple by 0.1

gcjr:
if your concerned about the complexity of a division by a constant, you can easily do the same with multiplication -- multiple by 0.1

What is the value of introducing the slowness and round off errors of floating point math when you can do the whole thing in integer math?

Hey,

am beginner.

My code is working fine, so this is just about finding the most streamlined approach.

I want to send a multiple-digit number to arduino via serial and dismante it into individual digits (and subsequently perform some math on the individual digits).

So far, I parse the multiple-digit number to an int, and use division and modulo on it to isolate the digits. Which works, but seems very bulky.

In a separate forum topic, someone gave me the hint that multiple digit numbers are transmitted digit-per-digit by serial. I verified this by sending a multiple-digit number to the arduino and have serial.read() and serial.println run in the loop function. As hoped, it printed the individual digits (in ascii format).

Problem is, if I added an serial.parseInt in there to store the incoming digit, the int's value would be overwritten with every new loop. So the question is (seems to be), how can you declare and fill a new/additional int with every loop? Would it be possible to increment an int's name for every loop, and could this be a viable solution? And are arrays necessary for any of this? (- unfortunately, do not know much about these yet)

Many thanks in advance, love arduino and this forum!

We can’t see your code.

Your description of what your program is doing with input is insufficiently clear. Please post the entire sketch in code tags, and explain its purpose.

Franzaforta:
In a separate forum topic, someone gave me the hint that multiple digit numbers are transmitted digit-per-digit by serial.

While it's true in your case, this is not true in all cases. You can also send values over serial in binary format (much more efficient and easier to work with IMHO).

You cannot "increment an int's name" - variable names are static.

What do you mean by "declare and fill a new int with every loop"? Why would you want to re-declare an int?

Lastly, why do you need to know the value of each digit in the first place?

An aside: You might be interested in checking out SerialTransfer.h.

i think the floating point multiply will be faster than the integer divide. if not sure, measure them

gcjr:
i think the floating point multiply will be faster than the integer divide. if not sure, measure them

Possibly. But the accuracy is insufficient. Have you forgotten that part of a 32 bit float value is the exponent? The OP is processing a long int.

Two aspects:

  • My code seems quite slow. It takes 2 seconds to print the results to the serial monitor. I assume my code is to bulky.

  • As stated, I am a beginner. I feel my code is very beginner style. It seems so repetitive/redundant, as far as naming the ints and the divisions are concerned. I imagine an experienced programmer would approach all of this on a more abstract level, and would like to know exactly how.

Many thanks in advance, love arduino and this forum.

Franzaforta:
Two aspects:My code seems quite slow. It takes 2 seconds to print the results to the serial monitor. I assume my code is to bulky.

No way. All the code you've shown above will execute in a few microseconds. Also you haven't responded to my question about your goals - efficiency vs. elegance.

I asked this in your other post, but why do you need each digit separately? Is it for display to something like an LCD?

Also, you can save processing time and memory if you save the digits to bytes instead of ints. Since D1, D2, D3... are not going to hold any values greater than 9, you don't need 16 bits to represent any of them.

aarg:
No way. All the code you've shown above will execute in a few microseconds.

Thought so, could be a different problem. My question was really more about how a skilled programmer would approach all of this. If there would be some speed gains too, thats also nice, I guess.

Power_Broker:
I asked this in your other post, but why do you need each digit separately? Is it for display to something like an LCD?

Also, you can save processing time and memory if you save the digits to bytes instead of ints. Since D1, D2, D3... are not going to hold any values greater than 9, you don't need 16 bits to represent any of them.

Here's the critical question. What you're going to do with these digits once you have them likely impacts the method you would use to achieve it.

maybe the most efficient way is to use sprintf and let it create a string with the digits.

gcjr:
maybe the most efficient way is to use sprintf and let it create a string with the digits.

From his other posts, the digits are already coming in as ASCII over the serial line. Now if we knew something about the format of the incoming data, the ASCII could be directly stored as digits instead of converting it to an int first.

Incidentally, it takes about 640uS to do it as illustrated in the initial post. Using a for statement, and avoiding the modulo operator, it can easily be done in less than 400uS, seems fast enough to me.

i do something like that as part of a larger function that accepts single letter commands

    if (Serial.available()) {
        int c = Serial.read ();

        switch (c)  {
        case '0':
        case '1':
        case '2':
        case '3':
        case '4':
        case '5':
        case '6':
        case '7':
        case '8':
        case '9':
            val = c - '0' + (10 * val);
            break;

TheMemberFormerlyKnownAsAWOL:
We can’t see your code.

I am sorry. I meant that the code is working where I break down the multiple-digit int using divisions and modulo.

For this question here, I do not have any code yet - I don’t know how to write it, unfortunately.

This could be a start:

void setup() {
  Serial.begin(9600);
  }

void loop() {
  while (Serial.available() > 0) {
    int1 = Serial.read();
    }
   }

If I send an multiple-digit number to arduino, this loop will store the first incoming digit to int1, then it will loop and store the second incoming digit in the same int1, and so on.

The good part about this is that serial already splits up the number in its digits. My question is simply: How could i program the arduino to store the first incoming digit in int1, but the second incoming digit in a different, second int (called e.g. int2), and so on?

I am sorry if I did not express this well - beginner & english not first language

What is the purpose of your project/what are you trying to accomplish with it? The answer to that question will help us give you better answers.