• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 315
  • Last Modified:

get a digit from a number without divide

Hello. I need a function that gets the digit from a number with only using *,^,+,- and the mod operator.

This function works, but it contains divide.

placement = to get the number from the end of the number to the right of the number

mod(floor(number/10^(placement-1)), 10)
0
m-jansen
Asked:
m-jansen
  • 21
  • 13
  • 2
  • +4
1 Solution
 
m-jansenAuthor Commented:
it's ok if it only works for numbers up to 10000
0
 
m-jansenAuthor Commented:
and floor is ok too
0
 
d-glitchCommented:
For any positive munber N:

      N - 10*mod( N, 10) will give you the last (units) digit.
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
d-glitchCommented:
Sorry.  That should be just

            mod( N, 10) will give you the last (units) digit.
0
 
m-jansenAuthor Commented:
How to get the seccond, third and fourth last?
0
 
d-glitchCommented:
You can multiply by 10 to a negative exponent to accomplish the necessary division:

       mod( 10^-1*(N - mod(N, 10))) will give you the second digit

       mod( 10^-2*(N - mod(N, 100))) will give you the third digit
0
 
d-glitchCommented:
Left out an argument:

       mod( 10^-1*(N - mod(N, 10)), 10) will give you the second digit

       mod( 10^-2*(N - mod(N, 100)), 10) will give you the third digit
0
 
d-glitchCommented:
If p=1 refers to the units digit,     p=2 the tens digit,   ...

then the following formula should work for digits of any length.

    mod( 10^(1-p)*(N - mod(N, 10^(p-1))), 10)    will give you the p-th digit

0
 
m-jansenAuthor Commented:
The right hand of ^ has to be a natural value. Is that possible?
0
 
d-glitchCommented:
I don't think so.  

Using the operators and functions you have specified, you can isolate any part of the number.

If   N= 8754

     mod( N,     10) =   4
     mod( N,   100) =  54
     mod( N, 1000) = 754

    mod( N,   100) =  54
     mod( N, 1000)  - mod( N, 100) =  754 - 54 = 700

You need a division to extract the digit "7" from 700.

You can divide by 100, or multiply by 10^(-2), or take 10^(log(700)-2),
or shift the character string two places to the right.  

But all of those operations are equivalent to division.

Where is this restriction against division coming from??
What are you trying to do??  Exactly.
0
 
CallandorCommented:
d-glitch,

It may be related to his Microchips question http://www.experts-exchange.com/Hardware/Microchips/Q_22042188.html, which you may know something about.
0
 
m-jansenAuthor Commented:
I try to get a specific number from an integer in order to use each digit in a four seven segment displays. :)
0
 
m-jansenAuthor Commented:
0
 
d-glitchCommented:
That means that your number is stored in a set of registers in BCD format, and that you probably have lots of logic functions available.

If you have four digits, you have to set up at least a 2-bit counter (0-3) to drive the common (anode or cathode) for each digit.

And you have to set up a logic function for each segment.

I have done this in a CPLD using CUPL.  It is slightly hairy, but not really that hard.  I copied each digit to a 4-bit buffer register to simplify the logic for each segment.

You should thing about the timing before you start writing code.  
0
 
d-glitchCommented:
I don't know VHDL or Verilog.

But this is digital logic/multiplexing problem, not a mathmatical problem.

The logic goes something like this:

If Count = 0  copy Digit_1 to BCD_Buffer
If Count = 1  copy Digit_2 to BCD_Buffer
If Count = 2  copy Digit_3 to BCD_Buffer
If Count = 3  copy Digit_4 to BCD_Buffer

Anode_1 = Count:{0}
Anode_2 = Count:{1}
Anode_3 = Count:{2}
Anode_4 = Count:{3}

Seg_A = BCD_Buffer: {0, 2, 3, 5, 7, 8, 9}        /* Top Segment */
Seg_B = BCD_Buffer: {0, 1, 2, 3, 4, 7, 8, 9}    /* Upper Right Segment */
:
:
:
0
 
m-jansenAuthor Commented:
Thanks this changes my focus.
0
 
m-jansenAuthor Commented:
I can't see what kind of coding system I use. This is the table for one seven segment segment. DP is comma or point I think. A is LSB.

Decimal      A      B      C      D      E      F      G      DP
0      1      1      1      1      1      1      0      1
1      0      1      1      0      0      0      0      1
2      1      1      0      1      1      0      1      1
3      1      1      1      1      0      0      1      1
4      0      1      1      0      0      1      1      1
5      1      0      1      1      0      1      1      1
6      1      0      1      1      1      1      1      1
7      1      1      1      0      0      0      0      1
8      1      1      1      1      1      1      1      1
9      1      0      0      1      1      1      1      1
0
 
m-jansenAuthor Commented:
I have a 12 bit vector with normal binary coding. How to use this 12 bit  vector? Is the idea that I need to divide this vector into 4 parts and then use each 3 bit part to find out each number that is represented?
0
 
d-glitchCommented:
Once again, on a higher level.  What exactly are you doing?

In particular, where does your 12-bit vector come from?

If you are counting something, that you need to display on a 7-segment display,
it would definitely be worth your while to use a BCD counter rather than a binary one.

If you don't have control of the input, i.e. you get a 12-bit binary number from someone
or somewhere else, then you probably have to convert the 12-bit binary data to BDC.

Once again, this is tedious but not difficult.  You need 15 or 16 equations for the BCD digits.

   12-bit binary ==>  0-4095 so the MSB for the thousands digit is always 0.



0
 
d-glitchCommented:
Another question:

Since you have asked about VHDL, I am assuming that this is a FPGA or CPLD project.  Correct?
If you have the option, it might be easier to do binary to BCD conversion with a microprocessor than with logic.

And how fast do the digits have to change?

0
 
m-jansenAuthor Commented:
I'm sorry I was a little to hasty there. The 12 bit vector I am talking about is an input and I think the format in this input is normal binary coding. This 12 bit input has untill now been converted to an integer (0-4096). And from that I have tried to extract each digit. And from that it would be possible to set each seven segment to the right value. But now I try to understand how to use this 12 bit value....

It's a FPGA project. The digits could change arround 50 hz.
0
 
m-jansenAuthor Commented:
How to use the 12 bit value without converting it to integer...
0
 
d-glitchCommented:
You have a 12-bit input:   0-4095

You have a 4-digit seven-segment display.  
Is it multiplexed, wth 7 segment lines and 4 common anode (or common cathode) lines?

Or does it have 28 (4x7) segment lines?

Another way to solve this problem is to use look-up tables.
You would need four 4095 x 8-bit tables, one for each digit.

1888 ==>  0000 0110     0111 1111     0111 1111     0111 1111

This might be the best way to program an FPGA.  I don't know for sure.
0
 
m-jansenAuthor Commented:
>Is it multiplexed, wth 7 segment lines and 4 common anode (or common cathode) lines?
Yes. It has 4 common cathode line and 7 segment lines and one extra segment line for a dot or point or something.
0
 
m-jansenAuthor Commented:
to see something on number one i must drive a 0 to the cathode that represents this number. and to light up the segments I must drive a 1 to these

cathode, segments
0111      1011 1111

would give me zero on the first digit from left
0
 
m-jansenAuthor Commented:
with the dot lighting as well...
0
 
d-glitchCommented:
I am assuming this is a school project.  Is that correct?

Another way to convert 12-bit binary to 4-digit BCD is to count it.

     You would load you input data into a binary down counter.
     You would load 0000 into a BCD up counter.
     Then you would clock both counters until the binary counter is all zeros.

This would take approximately 0.4 ms with a 10 MHz system clock.
The is negligible as far as the human eye is concerned.

Once you have the data converted to BCD, you would display it as I suggested in my earlier post.  [ 01:26PM EST ]

This approach will probably result in the simplest and shortest code.
0
 
m-jansenAuthor Commented:
Yes it is a scool project but I need some help because of my slow brain. You have been at big help so far.
0
 
m-jansenAuthor Commented:
the base clock speed is actually 10 MHz (Spartan2E)
0
 
m-jansenAuthor Commented:
I'll take a deeper look at this the next days.
0
 
d-glitchCommented:
Happy to help in a strategic sense.
I won't be able to help much with the VHDL though.

One thing you might try to get you started is to try displaying the 12-bit vector
as three BCD characters.

I'm guessing that this project in on the order of 100 lines of code and several full days of work.
0
 
MysidiaCommented:
You know you can do division with the ^  operator, right?

A^(-B)  =   1/A^B

So what's       number * 10^(-(placement - 1))     ?  :)


Shifting the decimal point to the left, truncating the stuff to the right, and taking mod 10 seems like a way to get any digit to me.
0
 
m-jansenAuthor Commented:
In my situation it's not legal to use negative constant on right side of arithmetic operator ^ or ** in VHDL
0
 
grg99Commented:

There is no simple way to convert a binary number to decimal.

One kloodgy way would be to take your 12 bit input, store it into a count-downable register, and then count it down to zero while you count up a BCD register.  Not very fast but doable with just a few chips, so I assume it's programmable in VDHL.


If you must do it really fast, and it's only 12 bits, you could use a 14-bit address by 8-bit wide EROM  (16K bytes).  Feed in 12 bits of the number and two bits of the digit you want and voila, out the data lines come your 7-segments (plus an exta bit for whatever else you want to do).





0
 
jkmyoungCommented:
mod(floor(number*0.1^(placement-1)), 10)
?
0
 
NovaDenizenCommented:
It's easy to do if you don't mind iterating.

int placesize = 10^(placement-1)  /* assumes placement=1 means ones digit */

n = n mod (placesize * 10);   /* gets rid of digits above our desired digit. Don't care about smaller digits */
result = 0;
while (n >= placesize) {
    n = n - placesize;
    result = result + 1;
}

result is now the digit you're looking for.
0
 
grg99Commented:
I don't see how he has mod but not divide available.  They're two sides to the same coin.

0
 
m-jansenAuthor Commented:
jkmyoung: yes that would work I think or....

n mod 10
for the last
n * 0.1 mod 10
for the seccond last
n * 0,01 mod 10
for the third last
n * 0,001 mod 10
for the seccond last
0
 
m-jansenAuthor Commented:
n * 0,001 mod 10
for the fourth last
0
 
m-jansenAuthor Commented:
jkmyoung: this gives me an answer to my problem. However it did not work in vhdl. Thanks everybody for the help. It's been too much.
0

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

  • 21
  • 13
  • 2
  • +4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now