Pages: [1] 2   Go Down
Author Topic: isolating a digit  (Read 1268 times)
0 Members and 1 Guest are viewing this topic.
Manchester NH
Offline Offline
Full Member
***
Karma: 1
Posts: 132
Like to build typing devices, and heard unicorns
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm trying to efficiently isolate a digit. For example If have two values x=1106 and y = 1000, I'm looking the compare the differences in a granular way by place value like so

tens place x is what to y tens place
what == equal
ones place x is what to y ones place
what == grater by 6

This post will become ridiculous fast if I explain the why portion of the problem.
Needless to say the part I'm having a hard time with is isolating the digits to make the comparisons.
Paying more attention in high school math probably would have helped me here...
anyhow, here is what I looked at as a possible example http://www.daniweb.com/software-development/cpp/threads/151273/integer-place-values
and here is where i'm at with test code.
Code:
#include<avr/pgmspace.h>

prog_uint16_t preDefLayout[28] PROGMEM=
//just a bunch of unsigned ints
{
  1100,23000,2300,21000,1000,30000,3100,20001,32000,1500,3002,3000,6600,53000,
  60000,11000,15000,6000,3200,10,600,45000,20003,33000,62000,1001,1,10000
};

void setup()
{
  Serial.begin(9600);
  for(int i=0;i<28;i++)
  {
    unsigned int num = pgm_read_word_near(preDefLayout +i);
    for (int d=0; d<5; d++)
    {
      unsigned int num= compare%(10^d);
      unsigned int digit = a/(10^(d-1));
      Serial.print(" ");
      Serial.print(digit);
    }
    Serial.println();
  }
}

void loop()
{
}
Logged

UK
Offline Offline
Shannon Member
****
Karma: 223
Posts: 12630
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
unsigned int num= compare%(10^d);

From the context I guess you expect 10^d to represent ten to the power d. Unfortunately ^ is the bitwise exclusive OR operator so is not going to do what you want. You could use pow() if you're determined to use this approach. However, it seems to me like a very strange algorithm and I can't imagine any problem that this approach is a sensible solution to.
Logged

I only provide help via the forum - please do not contact me for private consultancy.

Rome, Italy
Offline Offline
Sr. Member
****
Karma: 20
Posts: 442
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi, beware of redefining the num variable within the for block:

Code:
    unsigned int num = pgm_read_word_near(preDefLayout +i);
    for (int d=0; d<5; d++)
    {
      unsigned int num= compare%(10^d);

My approach would be: get the highest power of 10 less than the numbers to compare, take the leftmost digits from the numbers using division, compare them, discard the leftmost digit using the modulus operation, get the next lower power of 10, repeat the cycle.

This results in making the comparison from left to right, as in your requirement.

Code:
 unsigned long first_number_to_compare, second_number_to_compare;
// here assign some value to the numbers

  unsigned long max_number_to_compare =
        first_number_to_compare > second_number_to_compare ?
                first_number_to_compare : second_number_to_compare;

// get the highest power of 10 that is less than the highest number
  unsigned long magnitude = 1;
  while (magnitude * 10 < max_number_to_compare)
  {
    magnitude *= 10;
  }

// compare the numbers starting from the leftmost digit
  while (magnitude > 0)
  {
    int first_digit_to_compare = first_number_to_compare / magnitude;
    int second_digit_to_compare = second_number_to_compare / magnitude;
// here compare the digits, print something

// cut off the leftmost digit
    first_number_to_compare %= magnitude;
    second_number_to_compare %= magnitude;
    magnitude /= 10;
}
Logged

Manchester NH
Offline Offline
Full Member
***
Karma: 1
Posts: 132
Like to build typing devices, and heard unicorns
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
it seems to me like a very strange algorithm and I can't imagine any problem that this approach is a sensible solution to
Peter,
honestly it looked like gibberish to me too, I just trusted the person knew what they were doing, but I guess with my copy and paste methodology its a prime way to give a foolish example.

I found another example here http://www.cplusplus.com/forum/beginner/1326/ I'm just not sure how I can translate it to my problem.

spatula,
I'm still working out your solution in my head (l'm a bit of a dunce with math)  having a hard time visualizing how the modulus operation cuts off the leftmost digit.
Logged

Sydney, Australia
Offline Offline
Edison Member
*
Karma: 33
Posts: 1283
Big things come in large packages
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

The modulus operator gives you the remainder when you divide the number by the divisor.

So 16 mod 10 = 6, because 10 fits into 16 once with remainder 6. 42 mod 10 = 2, etc
Logged

Arduino libraries http://arduinocode.codeplex.com
Parola hardware & library http://parola.codeplex.com

Manchester NH
Offline Offline
Full Member
***
Karma: 1
Posts: 132
Like to build typing devices, and heard unicorns
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

thanks for for the explanation marco, I got that far, I was just not sure about
value=1106
value%=10
its this compound operator im not sure of, what is value equal to now?

I just tried a method comparing the ints a strings using itoa()...
that didn't go well  smiley-eek ... not even worth posting
itoa() seems to overflow when given an unsigned int with an unsigned'esk' value
and when blank spots in the buffer are compared they are random.
Logged

Ayer, Massachusetts, USA
Offline Offline
Edison Member
*
Karma: 54
Posts: 1857
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

thanks for for the explanation marco, I got that far, I was just not sure about
value=1106
value%=10
its this compound operator im not sure of, what is value equal to now?
The expression:

Code:
value %= 10;

is shorthand for:

Code:
value = value % 10;

The '%' operator is the modulus operator, which is equivalent to:

Code:
value = value - ((value / 10) * 10);

Note, integer division truncates, so if value was 1106 before the calculation, after 'value %= 10' it would hold 6.

So lets break it down:
1106 / 10 returns 110 (value / 10).
110 * 10 returns 1100 ((value / 10) * 10).
1106 - 1100 returns 6 (value - ((value / 10) * 10) or (value % 10).
Logged

Rome, Italy
Offline Offline
Sr. Member
****
Karma: 20
Posts: 442
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

thanks for for the explanation marco, I got that far, I was just not sure about
value=1106
value%=10
its this compound operator im not sure of, what is value equal to now?
The expression:

Code:
value %= 10;

is shorthand for:

Code:
value = value % 10;

@Paul, and this shorthand notation applies to other binary operators as well: +=, -=, *=, /=.
Where applicable, a op= b; is equivalent to a = a op b.

Thus, value = 1106 followed by value %= 10 will give you value = 6.
Now, allow me to expand a little bit: if value = 1106, what is value %= 1000
Logged

Sydney, Australia
Offline Offline
Edison Member
*
Karma: 33
Posts: 1283
Big things come in large packages
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
@Paul, and this shorthand notation applies to other binary operators as well: +=, -=, *=, /=.
Where applicable, a op= b; is equivalent to a = a op b.

Yes it does. It also applies to the logical operators |, &, ^, etc.

What's more, i++ is short for i+=1 which is short for i=i+1 smiley, but this form is only valud for ++ and --, not the other operators.
« Last Edit: April 04, 2013, 01:09:34 am by marco_c » Logged

Arduino libraries http://arduinocode.codeplex.com
Parola hardware & library http://parola.codeplex.com

UK
Offline Offline
Shannon Member
****
Karma: 223
Posts: 12630
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I just trusted the person knew what they were doing

Do you know what they're trying to achieve? Unless they're trying to do something really weird, there may well be a simpler way to achieve it.
Logged

I only provide help via the forum - please do not contact me for private consultancy.

0
Offline Offline
Shannon Member
****
Karma: 214
Posts: 12406
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I just trusted the person knew what they were doing

Do you know what they're trying to achieve? Unless they're trying to do something really weird, there may well be a simpler way to achieve it.

Absolutely, isolating a single digit is a very rare thing to want - usually you want to convert an integer to its
whole decimal expansion as a string in order to print it - in which case this is not the way to go about it, use
print or println.  So what is the overall thing that you're trying to achieve?
Logged

[ I won't respond to messages, use the forum please ]

Manchester NH
Offline Offline
Full Member
***
Karma: 1
Posts: 132
Like to build typing devices, and heard unicorns
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
So what is the overall thing that you're trying to achieve?

I'm correcting for noisy input, each of the 5 digits represents a independent button values combined into one unsigned int earlier in the program. 1 for a press, 3 for a hold and so on. In that way 300 would represent a hold on the 3rd button and 10000 would represent a press of the first. To correct for noise I need to calculate the level of difference by input.

Implicitly I can tell that if 300 hasn't been assigned to a letter my user probably doesn't wan't the letter assigned to 10000 but If there is a letter assigned to 600 which is just a longer hold of button 3 maybe they are trying to go for the letter assigned to 600. Its just more likely that is what they were trying to do, considering the input they used had not been assigned.

Applying an explicit probability algorithm that acts in a similar manner is the next step, but first I have to get those digits alone to compare the individual place cases. The way I figure it I can build up differance counter(s) and pick the assignment the generates the least difference.   

There is likely a way to do this before the int is compiled, but it would conflict with another part of my program.
I'll post the link to the main body once I push the current commit, so that you folks have a better idea of the purpose of the project.
Logged

Ayer, Massachusetts, USA
Offline Offline
Edison Member
*
Karma: 54
Posts: 1857
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Now, allow me to expand a little bit: if value = 1106, what is value %= 1000
Hmmm, a bit rusty on basic math?  The answer is 106.
Logged

Manchester NH
Offline Offline
Full Member
***
Karma: 1
Posts: 132
Like to build typing devices, and heard unicorns
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

here is the main body of code w/ out what I'm testing add for those that are curious

https://github.com/PaulBeaudet/JesterType/blob/master/JesterType.ino

Quote
Hmmm, a bit rusty on basic math?
Yes, I am!  but, I think spatula's intention was for me to think this out my self so I would get it

Basically 6106 or 5106 or 4106%= 1000 would be 106 thus the left most digit is being removed , and now I get it.
Thank you for bearing with me on that one, now I'll try to make a test program a report back.
« Last Edit: April 04, 2013, 11:24:10 am by Paul Beaudet » Logged

Manchester NH
Offline Offline
Full Member
***
Karma: 1
Posts: 132
Like to build typing devices, and heard unicorns
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I got things working  smiley-grin
sorry if abbreviating the variables bothers anyone. I always figure if its a problem I can just use the find & replace to fix.
Code:
#include<avr/pgmspace.h>

prog_uint16_t preDefLayout[28] PROGMEM=
//A to Z then yes then no.
{
  1100,23000,2300,21000,1000,30000,3100,20001,32000,1500,3002,3000,6600,53000,
  60000,11000,15000,6000,3200,10,600,45000,20003,33000,62000,1001,1,10000
};

unsigned int noise[5]= {3,6006,606,101,1010};
unsigned int chord;


void setup()
{
  Serial.begin(9600);
  for (int i=0;i<5;i++)
  {
    chord=filter(noise[i]);
    Serial.println(chord);
  }
}

void loop()
{
}

unsigned int filter(unsigned int noise)
{
  unsigned int correctToValue=9;
  //cant be nine so if it prints this something is wrong
  int lowPoint=15;
  for(int i=0;i<28;i++)
  {
    unsigned int largerNum;
    unsigned int compare = pgm_read_word_near(preDefLayout +i);
    unsigned int sComp=compare; //temporary second comparison
    unsigned int fComp=noise; //temp first comparison
    int pointCompare=0;
    if(fComp>sComp)
    {
      largerNum=fComp;
    }
    else
    {
      largerNum=sComp;
    };
    unsigned long mag= 1;
    while (mag*10<=largerNum)
    {
      mag*=10;
    }
    while(mag>0)
    {
      if(fComp>sComp)
        //overflow prevention
      {
        pointCompare+= fComp/mag - sComp/mag;
        Serial.print(fComp/mag - sComp/mag);
      }
      else
      {
        pointCompare+= sComp/mag-fComp/mag;
        Serial.print(sComp/mag-fComp/mag);
      }
      fComp%=mag;
      sComp%=mag;
      mag/=10;
      Serial.print(" ");
    }
    Serial.print(" total-");
    Serial.println(pointCompare);
    if(pointCompare<lowPoint)
      //filters to the path of least resistence
    {
      lowPoint=pointCompare;
      //set a new lowpoint
      correctToValue=compare;
      //remember the lowpoint value
    }
  }
  return correctToValue;
}

Thanks guys!

I have a couple thoughts about less iteration but I wonder If there are any inefficiencies that are obvious in what I wrote?
« Last Edit: April 04, 2013, 01:11:11 pm by Paul Beaudet » Logged

Pages: [1] 2   Go Up
Jump to: