Quantcast
Channel: Articles About Binary Numbers As They Exist Outside of Computers - Exploring Binary
Viewing all 17 articles
Browse latest View live

One Hundred Acorns in Binary

$
0
0

Today is the 100th day of school at my son’s elementary school. I’ve had my binary influence on prior 100th day projects, and this year was to be no different. But alas, his class is not doing one this year. I didn’t want to waste the acorn tops we saved though, so I made my own 100th day project (well not quite — I didn’t glue them):

A Binary Multiplication Problem Expressed With One Hundred Acorn Tops

A Binary Multiplication Problem Expressed With One Hundred Acorn Tops.

(Notice it’s a little asymmetric. The zero in the upper right has only 15 acorn tops, not 16 like the rest; I stole one for the times sign.)

There are two ways to solve this problem. The first way is to convert the operands to decimal and then multiply using decimal arithmetic:

  1. Binary 1010 = 1 x 23 + 0 x 22 + 1 x 21 + 0 x 20 = 23 + 21 = 8 + 2 = 10 decimal.
  2. 10 x 10 = 100.

The second way is to multiply using binary arithmetic and then convert the answer to decimal:

  1.       1010
        x 1010
        ------
          0000
         10100
        000000
       1010000
       -------
       1100100
    
  2. Binary 1100100 = 1 x 26 + 1 x 25 + 0 x 24 + 0 x 23 + 1 x 22 + 0 x 21 + 0 x 20 = 26 + 25 + 22 = 64 + 32 + 4 = 100 decimal.

The first way is easier, but it’s not as much fun :) .

By Rick Regan (Copyright © 2013 Exploring Binary)

One Hundred Acorns in Binary


Binary Multiplication

$
0
0

This is the third of a four part series on “pencil and paper” binary arithmetic, which I’m writing as a supplement to my binary calculator. The first article discusses binary addition; the second article discusses binary subtraction; this article discusses binary multiplication.

An Example of Binary Multiplication

Example of Binary Multiplication

The pencil-and-paper method of binary multiplication is just like the pencil-and-paper method of decimal multiplication; the same algorithm applies, except binary numerals are manipulated instead. The way it works out though, binary multiplication is much simpler. The multiplier contains only 0s and 1s, so each multiplication step produces either zeros or a copy of the multiplicand. So binary multiplication is not multiplication at all — it’s just repeated binary addition!

Decimal Multiplication

To multiply two multiple-digit decimal numbers, you first need to know how to multiply two single-digit decimal numbers. This requires the memorization of 100 facts, or 55 facts if you exclude the commutative or “turnaround” facts. These facts are usually represented in a “multiplication table,” also known as a “times table.” Example facts are 2 x 9 = 18, 9 x 7 = 63, and 1 x 6 = 6.

A multiplication problem is written with one number on top, called the multiplicand, and one number on the bottom, called the multiplier. The algorithm has two phases: the multiplication phase, where you produce what are called partial products, and the addition phase, where you add the partial products to get the result.

In the multiplication phase, the digits of the multiplier are stepped through one at a time, from right to left. Each digit of the multiplicand is then multiplied, in turn, by the current multiplier digit; taken together, these single-digit multiplications form a partial product. The answer to each single-digit multiplication comes from the multiplication table. Some of these answers are double-digit numbers, in which case the least significant digit is recorded and the most significant digit is carried over to be added to the result of the next single-digit multiplication.

For example, let’s multiply 3.87 and 5.3:

An Example of Decimal Multiplication

Example of Decimal Multiplication

There are two digits in the multiplier, so there are two partial products: 1161 and 19350. Each partial product has its own set of carries, which are crossed out before computation of the next partial product. Here is the multiplication phase, broken down into steps:

Steps of Decimal Multiplication (Multiplication Phase Only)

Steps of Decimal Multiplication (Multiplication Phase Only)

When the multiplication phase is done, the partial products are added, and the decimal point is placed appropriately. (If there were any minus signs, they would be taken into account at this point as well.) This gives the answer 20.511.

Binary Multiplication

Binary multiplication uses the same algorithm, but uses just three order-independent facts: 0 x 0 = 0, 1 x 0 = 0, and 1 x 1 = 1 (these work the same as in decimal). If you perform the multiplication phase with these facts, you’ll notice two things: there are never any carries, and the partial products will either be zeros or a shifted copy of the multiplicand.

Observing this, you’ll realize there’s no need for digit-by-digit multiplication, which means there’s no need to consult a times table — which means there’s no multiplication, period! Instead, you just write down 0 when the current digit of the multiplier is 0, and you write down the multiplicand when the current digit of the multiplier is 1.

In the introduction, I showed this example: 1011.01 x 110.1. I wrote it as if you followed the decimal algorithm to the letter. Here’s how it looks if you follow the simpler “write zero or multiplicand” algorithm (it’s the same result, but with blanks representing 0s; this matches better conceptually with what we are now doing):

An Example of Binary Multiplication (Simplified View)

Example of Binary Multiplication (Simplified View)

Here’s what the “multiplication” phase looks like, step-by-step:

Steps of Binary Multiplication (Multiplication Phase Only)

Steps of Binary Multiplication (Multiplication Phase Only)

Each step is the placement of an entire partial product, unlike in decimal, where each step is a single-digit multiplication (and possible addition of a carry).

In the addition phase, the partial products are added using binary addition, and then the radix point is placed appropriately. This gives the answer 1001001.001.

Checking the Answer

You can check the answer by converting the operands to decimal, doing decimal multiplication, and then converting the decimal answer to binary. 1011.01 = 11.25, and 110.1 = 6.5. Their product is 73.125, which is 1001001.001, the answer we got using binary multiplication.

You can also check the answer using my binary calculator.

Discussion

Computers don’t multiply in exactly this way, but they do exploit the simplified view of binary multiplication that I’ve described.

By Rick Regan (Copyright © 2013 Exploring Binary)

Binary Multiplication

Binary Division

$
0
0

This is the fourth of a four part series on “pencil and paper” binary arithmetic, which I’ve written as a supplement to my binary calculator. The first article discusses binary addition; the second article discusses binary subtraction; the third article discusses binary multiplication; this article discusses binary division.

An Example of Binary Division

Example of Binary Division

The pencil-and-paper method of binary division is the same as the pencil-and-paper method of decimal division, except that binary numerals are manipulated instead. As it turns out though, binary division is simpler. There is no need to guess and then check intermediate quotients; they are either 0 are 1, and are easy to determine by sight.

Decimal Division

Pencil-and-paper division, also known as long division, is the hardest of the four arithmetic algorithms. Like the other algorithms, it requires you to solve smaller subproblems of the same type. But unlike the other algorithms, there is no limited set of “facts” that solve all possible subproblems. Solving these division subproblems requires estimation, guessing, and checking. In addition to these division subproblems, multiplication and subtraction are required as well.

Let’s review how decimal division is done, so that we can set the stage for how division is done in binary. Here is an example:

An Example of Decimal Division

Example of Decimal Division

The algorithm is a series of steps, each step having these four substeps:

  1. Divide: Divide the working portion of the dividend by the divisor. (The dividend is the number under the line.)
  2. Multiply: Multiply the quotient (a single digit) by the divisor.
  3. Subtract: Subtract the product from the working portion of the dividend. (I don’t write down minus signs — they’re implied.)
  4. Bring down: Copy down the next digit of the dividend to form the new working portion.

Here’s the example again, step-by-step:

Steps of Decimal Division

Steps of Decimal Division

  • Step 0

    Does 88 go into 8? No, because it’s greater than 8. Does 88 go into 83? No, because it’s greater than 83. Does 88 go into 831? Yes, because it’s less than or equal to 831.

    (The first step of long division, as commonly practiced, combines several steps and their substeps into one. That’s why I call this step 0. Technically, 88 goes into 8 zero times, so we should write down a 0, multiply 88 by 0, subtract 0 from 8, and then bring down the 3. Next, we should write down a 0 because 88 goes into 83 zero times, multiply 88 by 0, subtract 0 from 83, and bring down the 1. We’re just eliminating a bunch of stuff that produces superfluous leading zeros.)

  • Step 1
    1. Divide: Does 88 go into 831? (Yes, we already know that from step 0.) How many times does it go in? 9 times. (Normally you have to guess the answer and do the multiplication and subtraction to verify you guessed correctly; I’ll just show the correct answer, to keep things from getting too messy.)
    2. Multiply: 9 x 88 = 792. (If 9 were a guess, your first check is to see if 792 is less than 831. It is, so so far, so good.)
    3. Subtract: 831 – 792 = 39. (If 9 were a guess, your second check is to see if 39 is less than 88. It is, so your guess was correct. Actually, in this case, this has to check out, since we can’t go higher than 9.)
    4. Bring down: Bring down the 2 to make 392.
  • Step 2
    1. Divide: Does 88 go into 392? Yes, 4 times.
    2. Multiply: 4 x 88 = 352.
    3. Subtract: 392 – 352 = 40.
    4. Bring down: Bring down the implied trailing 0 to make 400.
  • Step 3
    1. Divide: Does 88 go into 400? Yes, 4 times.
    2. Multiply: 4 x 88 = 352.
    3. Subtract: 400 – 352 = 48.
    4. Bring down: Bring down the implied trailing 0 to make 480.
  • Step 4
    1. Divide: Does 88 go into 480? Yes, 5 times.
    2. Multiply: 5 x 88 = 440.
    3. Subtract: 480 – 440 = 40.
    4. Bring down: Bring down the implied trailing 0 to make 400.
  • Step 5

    Stop the presses! We tried to divide 400 by 88 before — two steps ago. That means we have a two-digit cycle (45) from here on out. The answer is 9.445.

The red digits are the carries that occur during the multiplication substeps (the multiplication is done as if the divisor — the bigger number — is on top, by convention). Each red digit is crossed out before the next multiplication. To avoid clutter, I have chosen not to mark the borrows that occur during subtraction.

I Picked The Hardest Type of Example

My example has a multi-digit divisor, and has an answer with a remainder that I wrote as a repeating decimal. I wanted one example that showed long division to its fullest. I could have picked a problem with a single-digit divisor (which would require no guessing, assuming you know the multiplication facts), or one that produced an integer quotient, or one that produced a quotient with a fractional part that terminated. I could have expressed the fractional part as an integer remainder, or in fraction form.

Other Cases

  • If the divisor or dividend is negative, you can remove the signs and apply the appropriate sign to the answer at the end.
  • If the divisor has a decimal point, shift the decimal point right until the divisor is an integer, and shift the dividend by the same number of places.
  • If the divisor is greater than the dividend, just proceed with the algorithm as is. Trailing zeros will be brought down to form the appropriate subproblems.

Binary Division

Let’s return to the example of the introduction, 1011.11/11. Here it is broken down into steps, following the same algorithm I used for decimal numbers:

Steps of Binary Division

Steps of Binary Division

  • Step 0

    Does 11 go into 1? No, because it’s greater than 1. Does 11 go into 10? No, because it’s greater than 10. Does 11 go into 101? Yes, because it’s less than or equal to 101. (Remember, these are binary numerals; pronounce them “one-one”, “one-zero”, “one-zero-one”, etc.)

  • Step 1
    1. Divide: Does 11 go into 101? (Yes, we already know that from step 0.) How many times does it go in? One time. There is no guessing. It’s easy to see 11 is less than 101, so we know it goes in. And if it goes in, it goes in only once.
    2. Multiply: 1 x 11 = 11. (Remember how simple it is to “multiply” a binary number by a single digit — just copy the number down if that single digit is 1, or write down 0 if that single digit is 0.)
    3. Subtract: 101 – 11 = 10.
    4. Bring down: Bring down the 1 to make 101.
  • Step 2
    1. Divide: Does 11 go into 101? Yes, 1 time.
    2. Multiply: 1 x 11 = 11.
    3. Subtract: 101 – 11 = 10.
    4. Bring down: Bring down the 1 to make 101.
  • Step 3
    1. Divide: Does 11 go into 101? Yes, 1 time.
    2. Multiply: 1 x 11 = 11.
    3. Subtract: 101 – 11 = 10.
    4. Bring down: Bring down the 1 to make 101.
  • Step 4
    1. Divide: Does 11 go into 101? Yes, 1 time.
    2. Multiply: 1 x 11 = 11.
    3. Subtract: 101 – 11 = 10.
    4. Bring down: Bring down the 0 to make 100.
  • Step 5
    1. Divide: Does 11 go into 100? Yes, 1 time.
    2. Multiply: 1 x 11 = 11.
    3. Subtract: 100 – 11 = 1.
    4. Bring down: Bring down the 0 to make 10.
  • Step 6
    1. Divide: Does 11 go into 10? No (write down a 0).
    2. Multiply: (We don’t need to record this step; we’re just going to get 0.)
    3. Subtract: (We don’t need to record this step; we’re just going to get 10.)
    4. Bring down: Bring down the 0 to make 100.
  • Step 7

    We stop here, recognizing that we divided 100 by 11 two steps ago. This means we have a two-digit cycle (10) from here on out. The quotient is 11.1110.

Checking the Answer

When the answer has a repeating fractional part, checking it is not as straightforward as it is for the other arithmetic operations. What we can do is approximate the quotient to a finite number of places and then check that it comes close to the expected answer.

You can check the answer in a few ways. One way is by doing binary multiplication by hand: you verify that the approximated quotient (11.11101011, for example) multiplied by the divisor (11) equals the dividend (1011.11). (I’ll leave that as an exercise, but the answer is 1011.11000001, which is very close to 1011.11).

Another way to check is to convert the operands to decimal, do decimal division, and then convert the approximate decimal answer to binary. 1011.11 = 11.75, and 11 = 3. 11.75/3 = 3.916. Estimating that as 3.91666666666666667, for example, my binary converter says it equals 11.111010101010101010101010101010101010 when truncated to 36 places. That looks like it wants to be 11.1110, the answer we got using binary division.

You can also check the answer using my binary calculator. It says 1011.11/11 is 11.111010101010 (to 12 places, for example). Again, that looks like 11.1110.

If you want to verify the repeating part directly, you can use this conversion tool; here’s what to enter:

  • Initial Base: 2
  • Integral part: 11
  • Non-Repeating Fractional Part: 11
  • Repeating Fractional Part: 10
  • New Base: 10

It gives the decimal answer we expect: 3.916. (Actually, the more direct way to use this tool is to enter ‘2’ for ‘New Base’; this gives the fraction 101111/1100, which is equivalent to our division problem of 1011.11/11.)

You can also use this tool to convert in the opposite direction, verifying that 3.916 converts to 11.1110.

(There are also analytical ways to check the answer exactly: read my articles about the subtraction method, the direct method, and the series method.)

Discussion

Like the other arithmetic algorithms, I described the division algorithm in a base-independent way. I wanted to stress the mechanical procedure, not why it works (in either decimal or binary).

When you do binary long division, you might find yourself doing some of the substeps in your head in decimal (e.g., 101 – 11 is 5 – 3 = 2, which is 10 in binary).

Although binary division is easier than decimal division (because there’s no guessing and effectively no multiplication), you will find that always having the same number (the divisor) as the subtrahend will produce a pattern that will start mesmerizing you; it’s easy to get lost in that sea of 1s and 0s. (Be thankful my example only had a two-digit repeating cycle!)

If you play around with binary division you’ll see that it produces more repeating fractional numbers than decimal division does. For example, 2/5 = 0.4, but 10/101 = 0.0110.

Further Reading

There are many explanations of binary division on the Web; one that I like in particular, and that comes closest to what I’ve explained, is Dr. Math’s “Long Division in Binary.”

By Rick Regan (Copyright © 2013 Exploring Binary)

Binary Division

Bicimals

$
0
0

There is no widely accepted term for fractional binary numbers like 0.11001. A fractional decimal number like 0.427 is called a decimal or decimal fraction. A fractional binary number is called many things, including binary fraction, binary decimal, binary expansion, bicimal, binimal, binary radix fraction, and binary fractional (my term). In this article, I’m going to argue that bicimal should be the universal term.

(Please let me know what you think — take the poll at the end of this article.)

Why I Don’t Like ‘Binary Fraction’

Of all the existing terms, binary fraction is probably the most commonly used. I don’t like it because its analog, decimal fraction, is not clearly defined. I want to avoid a term that inherits this problem.

Decimal fraction is commonly defined as any number with an explicit or implicit power of ten denominator, either entirely fractional or not. For example, 254/1000, 0.254, 15/10, and 1.5 are decimal fractions. But what about 2/5? It can be written as 4/10 or 0.4, although as written its denominator is not a power of ten. And what about 1/3? Its equivalent form as a decimal is 0.3 — a repeating decimal. It can never be written with a power of ten denominator. To make things more confusing, 2/5 and 1/3 are fractions — fractions written in decimal numerals.

You could argue that decimal fraction includes 2/5 but excludes 1/3 and still have a reasonable definition. However, I’m looking for the equivalent of decimal, a term which includes 0.4 and 0.3, but excludes 2/5, 4/10, and 1/3.

‘Bicimal’

I discovered the term bicimal on the Web and in Google Books, but I don’t know its origin. I pronounce it “bye’ suh mull”, or as Merriam-Webster might express it, \ˈbī-sə-məl\. A bicimal is built with negative powers of two, whereas a decimal is built with negative powers of ten.

Like the term decimal, bicimal usually means a pure fractional value, like 0.11001. However, in some contexts, it could mean numbers with a whole and fractional part, like 101.11. In this case, nonnegative powers of two come into play — for the whole part.

Why I Like ‘Bicimal’

Ideally, there would be a base-independent term for the fractional part of a number. I invented the term fractional for this purpose. I’ve called a fractional decimal number a decimal fractional, and a fractional binary number a binary fractional. The purpose of this new term was to separate the form of a number — a number with a “point” in it — from its base. If 0.427 is a decimal, does that make 0.11001 a binary decimal? You can see why we need a better term.

One problem with my terminology is that I’ve created two terms (decimal fractional and binary fractional) when I really only needed to create one. Why not stick with decimal and invent a new term just for binary? Decimal is easier to say than decimal fractional, and everyone knows what it means. So what’s a good replacement for binary fractional? I’ve come to like the term bicimal.

At first glance, there’s not much to like about bicimal. It’s base-dependent, and it is a portmanteau for binary decimal. It is a poorly formed portmanteau at that. While the prefix ‘bi-’ is perfectly acceptable, its pairing with the suffix ‘-cimal’ seems ill-formed. Binimal seems linguistically the better choice; it swaps out the prefix ‘dec-’ for the prefix ‘bin-’ and retains the suffix ‘-imal’.

On the other hand, say bicimal and binimal outloud, over and over; I think you’ll find that bicimal sounds better, as do its associated terms: bicimal point, bicimal places, bicimal part, terminating bicimal, repeating bicimal, infinite bicimal, etc. And bicimal produces natural sounding phrases like “multiply bicimals”, “convert a decimal to a bicimal”, “convert a bicimal to a decimal”, “convert a bicimal to a fraction”, “convert a fraction to a bicimal”, etc.

I think bicimals will be immediately understood by newcomers. It evokes all the feelings and terminology and operations of decimals (for better or worse :) ). I don’t think binimals — or any of the alternative terms — has this property. So all things considered, I like bicimal the best.

What Do You Think?

Please leave a comment or take the poll (Polldaddy poll is available only if Javascript is enabled). If you like binary fraction, please tell me why. Also, please tell me how you’d pronounce bicimal — “bye’ suh mull” (‘bi-’ with a long i) or “bih’ suh mull” (‘bi-’ with a short i).

By Rick Regan (Copyright © 2013 Exploring Binary)

Bicimals

Converting a Bicimal to a Fraction (Subtraction Method)

$
0
0

In my article “Binary Division” I showed how binary long division converts a fraction to a repeating bicimal. In this article, I’ll show you a well-known procedure — what I call the subtraction method — to do the reverse: convert a repeating bicimal to a fraction.

Equivalent Representations of 47/12, in Binary

Equivalent Representations of 47/12, in Binary

Bicimals

A bicimal is the base-two analog of a decimal; it has a bicimal point and bicimal places, and can be terminating or repeating.

A terminating bicimal has a finite number of bicimal places; a repeating bicimal (also known as a recurring bicimal or periodic bicimal) has an infinite number of bicimal places, due to a sequence of digits that repeat forever. There are two types of repeating bicimals: pure repeating (also known as immediate repeating or strictly repeating) and mixed repeating (also known as delayed repeating). In a pure repeating bicimal, the repeating part (also known as the repetend) starts immediately after the bicimal point. In a mixed repeating bicimal, a non-repeating part starts immediately after the bicimal point; it is then followed by a repeating part.

Here are some examples:

  • 0.1101 (a terminating bicimal).
  • 101.01 (a pure repeating bicimal).
  • 11.1110 (a mixed repeating bicimal).

Like decimals, bicimals are created from fractions through long division. Also like decimals, bicimals can be converted back to fractions. You convert a bicimal to a fraction the same way you convert a decimal to a fraction — you just work in binary instead of decimal, and use powers of two instead of powers of ten.

A terminating bicimal is easy to convert to a fraction: the numerator of the resulting fraction is the bicimal itself, treated as an integer; the denominator is 2n, where n is the number of bicimal places. For example, 0.1101 = 1101/24 = 1101/10000 (which in decimal equals 13/16 = 0.8125). (Notice how I mixed decimal and binary numerals. Although potentially confusing, it is common practice, and actually makes things easier. I will be doing this throughout the article.)

Repeating bicimals take more work to convert. There are several methods; I will describe the subtraction method.

Subtraction Method

In the subtraction method, you take a bicimal b and create an expression that subtracts out its repeating part, and then rewrite that expression so that b is expressed as a fraction. Specifically, you create two nonnegative power of two multiples of b, mb and nb, such that mbnb = i, where i is an integer. Using simple algebra, you rewrite this expression as a fraction: b(m-n) = i, or b = i/(m-n).

Here is a straightforward way to pick m and n. Let p be the length of the non-repeating part, and let r be the length of one cycle of the repeating part. Choose m = 2p+r, and choose n = 2p. These values of m and n shift b left by differing numbers of places, creating new bicimals with identical fractional parts but different integer parts. (For pure repeating bicimals, p will be 0 and thus n will be 1, so nb = b; that is, it’s not shifted.)

Examples

Example 1: 101.01 = 10000/11

Consider the pure repeating bicimal b = 101.01. Picking m = 22 = 4 shifts b left by two places, giving 10101.01. Now if we subtract b from that, we will remove the fractional part (leaving b as is means we’ve picked n = 20 = 1). Let’s show the subtraction algebraically, in mixed decimal and binary numerals:

mbnb

4bb = 10101.01 – 101.01

3b = 10000

11b = 10000

b = 10000/11

which in decimal equals 16/3 = 5.3.

Example 2: 11.1110 = 101111/1100

Consider the mixed repeating bicimal b = 11.1110. Picking m = 24 = 16 will shift b left by four places — pulling out the non-repeating part and one cycle of the repeating part — giving 111110.10. Picking n = 22 = 4 will shift a copy of b left by two places — pulling out just the non-repeating part — giving 1111.10. Now let’s do the algebra:

mbnb

16b – 4b = 111110.10 – 1111.10

12b = 101111

1100b = 101111

b = 101111/1100

which in decimal equals 47/12 = 3.916.

Examples Redone Using Only Binary Numerals

You can perform the subtraction method using only binary numerals (thanks James for the comment); I will redo the two examples in this way.

Example 1: 101.01 = 10000/11

mbnb

100bb = 10101.01 – 101.01

11b = 10000

b = 10000/11

Example 2: 11.1110 = 101111/1100

mbnb

10000b – 100b = 111110.10 – 1111.10

1100b = 101111

b = 101111/1100

A Way to Avoid Binary Arithmetic on the Left Hand Side

The binary subtraction on the left hand side of the equation can be avoided; let’s manipulate the left hand side algebraically (remember that m = 2p+r and n = 2p):

mbnb

2p+rb – 2pb

2p(2rbb)

2pb(2r – 1)

(2r – 1)2pb

You don’t need to do any arithmetic to compute (2r – 1)2p: it is a string of r 1s followed by p 0s. For example 1, r = 2 and p = 0 gives 11; for example 2, r = 2 and p = 2 gives 1100.

On Going Directly to a Fraction Written in Binary

If you look around the Web (for example, Wikipedia), you’ll see this procedure is typically used to convert a bicimal straight to a fraction written in decimal numerals. For example 2, the steps would be:

mbnb

16b – 4b = 111110.10 – 1111.10

12b = 47

b = 47/12

which you’d then say is 101111/1100 in binary.

Conceptually, I see the process as bicimal -> fraction written in binary -> fraction written in decimal -> decimal, which is why I prefer my presentation.

Equivalent Representations of 47/12, In Binary and Decimal

Equivalent Representations of 47/12, in Binary and Decimal

Other Methods

Read my articles about the direct method and the series method — two other ways to convert a bicimal to a fraction.

By Rick Regan (Copyright © 2013 Exploring Binary)

Converting a Bicimal to a Fraction (Subtraction Method)

Converting a Bicimal to a Fraction (Direct Method)

$
0
0

There are several ways to convert a repeating bicimal to a fraction. I’ve shown you the subtraction method; now I’ll show you the direct method, my name for the method that creates a fraction directly, using a numerator and denominator of well-known form.

Example of Direct Method (7/12 in Decimal)

Example of Direct Method (7/12 in Decimal)

Converting a Repeating Decimal To a Fraction

A repeating decimal can be written as a fraction with a numerator derived from its digits and a denominator consisting of one or more 9s followed by zero or more 0s. This follows directly from the subtraction method. I’ll show you how to use the direct method to convert decimals, and then I’ll show you how it adapts trivially to convert bicimals.

Pure Repeating Decimals

A pure repeating decimal corresponds to a fraction with a numerator made up of the repeating digits and a denominator made up of as many 9s as there are repeating digits. Let’s take 0.142857 for example. The numerator of the fraction is 142857, and the denominator is six 9s; this makes the fraction 142857/999999, which reduces to 1/7. The subtraction method shows why it works out this way:

106dd = 142857.142857 – 0.142857

(106 – 1)d = 142857

d = 142857/(106 – 1)

d = 142857/999999

The denominator, 106 – 1, is six 9s. To generalize, if r is the length of the repeating part, then the denominator is 10r – 1; that is, r 9s. The numerator will always be the repeating digits, expressed as an integer.

Mixed Repeating Decimals

A mixed repeating decimal also corresponds to a fraction with a simple pattern, although you need to do a little more work to construct it. The denominator is formed easily: it starts with as many 9s as there are repeating digits, and ends with as many 0s as there are non-repeating digits. The numerator is formed by subtraction: you subtract an integer made of the non-repeating digits from an integer made of the non-repeating digits and repeating digits.

Let’s take 0.42866 for example. The numerator of the fraction is 42866-42 = 42824, and the denominator is three nines followed by two 0s; this makes the fraction 42824/99900, which reduces to 10706/24975. Let’s use the subtraction method to show why it works:

105d – 102d = 42866.866 – 42.866

(105 – 102)d = 42824

102(103 – 1)d = 42824

(103 – 1)102d = 42824

d = 42824/((103 – 1)102)

d = 42824/99900

The denominator is (103 – 1)102. The factor 103 – 1 represents three leading 9s, and the factor 102 represents two trailing 0s. To generalize, if r is the length of the repeating part and p is the length of the non-repeating part, then the denominator is (10r – 1)10p; that is, r 9s followed by p 0s. The numerator will always be the non-repeating and repeating digits minus the non-repeating digits.

Decimals with Whole Parts

A decimal with a whole part, like 17.12 or 312.1378, is handled by treating the whole and fractional parts separately. First, convert the fractional part to a fraction, as above. Then, using the denominator of that fraction, write the whole part as an improper fraction, and then add the two fractions.

For example, let’s convert the pure repeating decimal 17.12 to a fraction. 0.12 = 12/99, and 17 = 1683/99. These add to 1695/99, which reduces to 565/33.

The mixed repeating decimal 312.1378 is done similarly. 0.1378 = 1365/9900, and 312 = 3088800/9900. These add to 3090165/9900, which reduces to 206011/660.

Converting a Repeating Bicimal To a Fraction

At this point you know almost everything you need to know about how to convert a bicimal to a fraction. You do it the same way you convert a decimal to a fraction, except you use a denominator that contains a string of 1s instead of a string of 9s. I’ll demonstrate the procedure with two examples: 0.01 and 0.10010.

0.01 is a pure repeating bicimal with a two-digit repeating cycle. The numerator of the fraction is 1, and the denominator is 11; it converts to 1/11, which is 1/3 in decimal numerals.

0.10010 is a mixed repeating bicimal. It has a three-digit non-repeating prefix and a two-digit repeating cycle; this makes the denominator of the fraction 11000. The numerator is the non-repeating digits and repeating digits minus the non-repeating digits: 10010 – 100 = 1110. The resulting fraction is 1110/11000, which reduces to 111/1100, which is 7/12 in decimal numerals. (See the diagram in the introduction; the purple digits correspond to the non-repeating part, and the red digits correspond to the repeating part.)

Converting a bicimal with a whole part works the same as for decimals, except you form the improper fraction for the whole part using binary multiplication. For example, to convert 101.01, first convert the fractional part to 1/11, and then convert 101 to 1111/11 by multiplying 101 by 11. Add these two fractions to get the answer: 10000/11.

Why It Works

You can show why this method works by using the subtraction method, as we did for decimals. For example, the subtraction method will show you that the denominator is of the form (2r – 1)2p, where r is the length of the repeating part and p is the length of the non-repeating part — in other words, r 1s followed by p 0s.

(Read about the series method, my final article in this series.)

By Rick Regan (Copyright © 2013 Exploring Binary)

Converting a Bicimal to a Fraction (Direct Method)

Converting a Bicimal to a Fraction (Series Method)

$
0
0

I’ve shown you two ways to convert a bicimal to a fraction: the subtraction method and the direct method. In this article, I will show you a third method — a common method I call the series method — that uses the formula for infinite geometric series to create the fraction.

Viewing Repeating Decimals as Infinite Series

First, let’s take a look at repeating decimals. The repeating portion of the decimal can be modeled as an infinite geometric series. For example, consider the (pure) repeating decimal 0.39:

0.39 = 0.393939…

= 0.39 + 0.0039 + 0.000039 + …

= 39/100 + 39/10000 + 39/1000000 + …

= 39(1/100 + 1/10000 + 1/1000000 + … )

= 39(1/102 + 1/104 + 1/106 + …)

= 39(1/(102)1 + 1/(102)2 + 1/(102)3 + …)

= 39((1/102)1 + (1/102)2 + (1/102)3 + …)

\mbox{\footnotesize{\displaystyle = 39\sum_{i=1}^\infty \left(\frac{1}{10^{2}}\right)^{i}}}

The summation notation (∑) is just a concise way to represent an infinite sum. We can compute that sum — and use it in place of the summation — by using a variation on a well-known formula. This will allow us to express the decimal as a fraction.

Infinite Series Formula

The formula that represents an infinite geometric series (with a first term of ‘1’) is usually stated as such:

\mbox{\footnotesize{\displaystyle\sum_{i=0}^\infty r^{i} = \frac{1}{1-r}}} ,

where |r| < 1.

I think a repeating decimal is more naturally modeled as a series starting at i = 1, as my derivation in the above example shows. Let’s adjust the starting point and derive a new formula to apply in this case. This is done simply, by subtracting r0 = 1 from the right hand side:

\mbox{\footnotesize{\displaystyle \frac{1}{1-r} \; $-$ \; 1}}}

\mbox{\footnotesize{\displaystyle = \frac{1}{1-r} \; $-$ \;}}} \mbox{\footnotesize{\displaystyle\frac{1-r}{1-r}}}}

\mbox{\footnotesize{\displaystyle = \frac{1-(1-r)}{1-r}}}}

\mbox{\footnotesize{\displaystyle = \frac{r}{1-r}}}}

So the formula for starting at i = 1 is

\mbox{\footnotesize{\displaystyle\sum_{i=1}^\infty r^{i} = \frac{r}{1-r}}}}

Completing the Example

Let’s go back to our example; this is where we left it:

0.39 =

\mbox{\footnotesize{\displaystyle 39\sum_{i=1}^\infty \left(\frac{1}{10^{2}}\right)^{i}}}

Let’s remove the summation by applying the formula with r = 1/102:

\mbox{\footnotesize{\displaystyle \frac{r}{1-r}}}}

\mbox{\footnotesize{\displaystyle = \frac{\frac{1}{10^{2}}}{1-\frac{1}{10^{2}}}}}}

\mbox{\footnotesize{\displaystyle = \frac{\frac{1}{10^{2}}}{\frac{10^{2}-1}{10^{2}}}}}}

\mbox{\footnotesize{\displaystyle = \frac{1}{10^{2}-1}}}}

\mbox{\footnotesize{\displaystyle = \frac{1}{99}}}}

Now multiply this by 39 to get our answer: 0.39 = 39/99.

Generalizing the Formula

The above analysis applies to any pure repeating decimal. The integer made up of the repeating digits is multiplied by the infinite series that uses r = 1/10n, where n is the length of the repeating cycle. By the formula, the value of the series is 1/(10n – 1), a unit fraction with a denominator of n 9s.

Mixed Repeating Decimals

The infinite series method only works for pure repeating decimals. If you want to use it on a mixed repeating decimal, you’ll have to shift the non-repeating part to the left of the decimal point, and then apply the method to the remaining (pure repeating) fractional part. You then have to add in the whole part and divide by the power of ten used to shift the decimal.

For example, take 0.135954. Shift it left three places (multiply by 103) to get 135.954. Apply the series method to 0.954, getting 954/999. Add 135 = 134865/999 to it, getting 135819/999. Finally, divide it by 103 to undo the shifting, getting 135819/999000 = 15091/111000.

The Series Method for Bicimals

The infinite series formula works for bicimals as well; you just work in powers of two instead of powers of ten. For example, let’s convert 0.101 to a fraction:

0.101 = 0.101101101…

= 0.101 + 0.000101 + 0.000000101+ …

= 101/1000 + 101/1000000 + 101/1000000000 + …

= 5/8 + 5/64 + 5/512 + … (converting to decimal numerals makes it easier)

= 5(1/8 + 1/64 + 1/512 + … )

= 5(1/23 + 1/26 + 1/29 + …)

= 5(1/(23)1 + 1/(23)2 + 1/(23)3 + …)

= 5((1/23)1 + (1/23)2 + (1/23)3 + …)

\mbox{\footnotesize{\displaystyle = 5\sum_{i=1}^\infty \left(\frac{1}{2^{3}}\right)^{i}}}

Now remove the summation by applying the formula with r = 1/23:

\mbox{\footnotesize{\displaystyle \frac{r}{1-r}}}}

\mbox{\footnotesize{\displaystyle = \frac{\frac{1}{2^{3}}}{1-\frac{1}{2^{3}}}}}}

\mbox{\footnotesize{\displaystyle = \frac{\frac{1}{2^{3}}}{\frac{2^{3}-1}{2^{3}}}}}}

\mbox{\footnotesize{\displaystyle = \frac{1}{2^{3}-1}}}}

\mbox{\footnotesize{\displaystyle = \frac{1}{7}}}}

Multiply this by 5 to get our answer: 0.101 as a fraction is 5/7, or in binary, 101/111.

This method also generalizes to any pure repeating bicimal with cycle n. By the formula, the value of the series is 1/(2n – 1), a unit fraction with a denominator of n 1s.

(Mixed repeating bicimals can be handled just as mixed repeating decimals, except the shifting is in powers of two and not powers of ten.)

Comparing the Three Methods

Of the three methods, I think the subtraction method is the best. It handles all numbers uniformly, whether pure repeating or mixed repeating or whether there is a whole number part or not. The direct method is the quickest, but you have to handle three cases (pure repeating, mixed repeating, and numbers with whole parts). The series method is a little “scary” in that it uses infinite sums, and also requires handling of separate cases.

The direct method is nice because you know the denominator patterns directly: decimals have fractions with denominators of all 9s or 9s followed by 0s, and bicimals have fractions with denominators of all 1s or 1s followed by 0s. In a sense, the subtraction and series methods serve as proofs of the direct method; they explain the patterns the direct method produces.

By Rick Regan (Copyright © 2013 Exploring Binary)

Converting a Bicimal to a Fraction (Series Method)

“0.1 Repeating” In Binary Equals 1

$
0
0

In decimal, “0.9 repeating”, or 0.9, equals 1. In binary, a similar thing is true: “0.1 repeating”, or 0.1, equals 1. I’ll show you three ways to prove it, using the three bicimal to fraction conversion algorithms I described recently.

Proof Using the Series Method

A repeating bicimal is really an infinite geometric series, so one way to prove 0.1 = 1 is to use the series method:

0.1 = 0.111…

= 0.1 + 0.01 + 0.001 + …

= 1/10 + 1/100 + 1/1000 + …

= 1/2 + 1/4 + 1/8 + … (converting to decimal numerals makes it easier)

= 1/21 + 1/22 + 1/23 + …

= (1/2)1 + (1/2)2 + (1/2)3 + …

\mbox{\footnotesize{\displaystyle = \sum_{i=1}^\infty \left(\frac{1}{2}\right)^{i}}}

As I showed when I described the series method, that summation resolves to the formula

\mbox{\footnotesize{\displaystyle \frac{r}{1-r}}}},

where r = 1/2 in this case:

\mbox{\footnotesize{\displaystyle \frac{r}{1-r} = \frac{\frac{1}{2}}{1-\frac{1}{2}} = \frac{\frac{1}{2}}{\frac{1}{2}} = 1}}}

What Did We Prove Exactly?

This proof convinces you only inasmuch as you accept the proof of the formula for infinite geometric series. It’s a tough thing to accept at first — infinity is a strange concept. You have to think of the series as a fixed sum, not as a never-ending process of adding tinier and tinier numbers that gets you ever so close to — but never equal to — 1.

Proof Using the Subtraction Method

You can also prove 0.1 = 1 using the subtraction method:

b = 0.1

10b = 1.1

10bb = 1

b = 1

(All numerals are in binary.)

Look at that: b started out as 0.1 and ended up as 1; it’s 0.1 and 1 at the same time!

What Did We Prove Exactly?

This looks like mathematical sleight of hand. We shifted the bicimal left, yet the fractional part remained unchanged. And we subtracted an infinite string of 1s from an infinite string of 1s — is that legal? In the land of infinity, this is OK.

Proof Using the Direct Method

You can prove 0.1 = 1 using the direct method, which is really just a distillation of the series and subtraction methods. The direct method says to treat the repeating portion as an integer, and to place that integer over a denominator consisting of as many 1s as there are digits in the repeating portion. 0.1 is a pure repeating bicimal with a repeating cycle of one digit, so the fraction it converts to is 1/1; in other words, 1.

Discussion

In binary, 0.1 is another name for 1. Similar dual naming exists for all bicimals: just as decimal 0.29 = 0.3 and 0.1589 = 0.159, binary 0.01 = 0.1 and 0.10101 = 0.1011. The trailing repeating 1s are the same as a 1 in the next higher place. You can show this using the same three methods above.

By Rick Regan (Copyright © 2013 Exploring Binary)

“0.1 Repeating” In Binary Equals 1


Googling ‘Binary’ Returns Count of Results In Binary

$
0
0

I just noticed something cute: if you Google binary, Google returns its count of results in binary. Here’s a screenshot:

Google Returns Count of Results In Binary

The first line says “About 0b1000110100100100110100000000 results”. '0b' is the prefix for binary constants; 1000110100100100110100000000 in binary equals 148,000,000 in decimal.

This appears only to work for the single term binary; multi-word terms like binary number return the count as normal. You have to be logged out of Google to see this.

(Interestingly, though I rank well for many binary-related terms, I’m essentially unranked for this term. My first hit is on page 35 of the search results — my binary-calculator!)

Update 11/15/12: This is known as an easter egg; this one has been around for at least eight months (for example, see this Youtube video: “Google Binary Easter Egg for Numeral Nerds”).

By Rick Regan (Copyright © 2013 Exploring Binary)

Googling ‘Binary’ Returns Count of Results In Binary

Number of Bits in a Decimal Integer

$
0
0

Every integer has an equivalent representation in decimal and binary. Except for 0 and 1, the binary representation of an integer has more digits than its decimal counterpart. To find the number of binary digits (bits) corresponding to any given decimal integer, you could convert the decimal number to binary and count the bits. For example, the two-digit decimal integer 29 converts to the five-digit binary integer 11101. But there’s a way to compute the number of bits directly, without the conversion.

Sometimes you want to know, not how many bits are required for a specific integer, but how many are required for a d-digit integer — a range of integers. A range of integers has a range of bit counts. For example, four-digit decimal integers require between 10 and 14 bits. For any d-digit range, you might want to know its minimum, maximum, or average number of bits. Those values can be computed directly as well.

In this article, I will show you those calculations. I will be discussing pure binary and decimal, not computer encodings like two’s complement, fixed-point, floating-point, or BCD. All of the discussion assumes positive integers, although it applies to negative integers if you temporarily ignore their minus signs. 0 is a special case not covered by the formulas, but obviously it has only 1 bit.

(I use the terms decimal integer and binary integer when I really mean “an integer expressed in decimal numerals” and “an integer expressed in binary numerals”. An integer is an integer, independent of its base.)

Number of Bits in a Specific Decimal Integer

A positive integer n has b bits when 2b-1n ≤ 2b – 1. For example:

  • 29 has 5 bits because 16 ≤ 29 ≤ 31, or 24 ≤ 29 ≤ 25 – 1
  • 123 has 7 bits because 64 ≤ 123 ≤ 127, or 26 ≤ 123 ≤ 27 – 1
  • 967 has 10 bits because 512 ≤ 967 ≤ 1023, or 29 ≤ 967 ≤ 210 – 1

For larger numbers, you could consult a table of powers of two to find the consecutive powers that contain your number.

To see why this works, think of the binary representations of the integers 24 through 25 – 1, for example. They are 10000 through 11111, all possible 5-bit values.

Using Logarithms

The above method can be stated another way: the number of bits is the exponent of the smallest power of two greater than your number. You can state that mathematically as:

bspec = ⌊log2(n)⌋ + 1

That formula has three parts:

  • log2(n) means the logarithm in base 2 of n, which is the exponent to which 2 is raised to get n. For example, log2(123) ≈ 6.9425145. The presence of a fractional part means n is between powers of two.
  • x is the floor of x, which is the integer part of x. For example, ⌊6.9425145⌋ = 6. You can think of ⌊log2(n)⌋ as the exponent of the highest power of two in the binary representation of n.
  • + 1 takes the exponent to the next higher power of two. You can think of this step as accounting for the 20th place of your binary number, which then gives you its total number of bits. For our example, that’s 6 + 1 = 7.

You might be tempted to use the ceiling function — ⌈x⌉, which is the smallest integer greater than or equal to x — to compute the number of bits as such:

bspec = ⌈log2(n)⌉

However, this fails when n is a power of two.

Number of Bits in a d-Digit Decimal Integer

A positive integer n has d decimal digits when 10d-1n ≤ 10d – 1. How many bits do numbers in this range require? It varies. For example, consider four-digit decimal integers. Using the above formula you’ll see that the smallest four-digit number, 1000, requires 10 bits, and the largest four-digit number, 9999, requires 14 bits. The number of bits varies between those extremes. For example, 1344 requires 11 bits, 2527 requires 12 bits, and 5019 requires 13 bits. Why does this occur? Because that single power of ten range spans all or part of five consecutive power-of-two ranges. Here’s how the examples look from that viewpoint:

  • 1000 has 10 bits because 512 ≤ 1000 ≤ 1023, or 29 ≤ 1000 ≤ 210 – 1
  • 1344 has 11 bits because 1024 ≤ 1344 ≤ 2047, or 210 ≤ 1344 ≤ 211 – 1
  • 2527 has 12 bits because 2048 ≤ 2527 ≤ 4095, or 211 ≤ 2527 ≤ 212 – 1
  • 5019 has 13 bits because 4096 ≤ 5019 ≤ 8191, or 212 ≤ 5019 ≤ 213 – 1
  • 9999 has 14 bits because 8192 ≤ 9999 ≤ 16383, or 213 ≤ 9999 ≤ 214 – 1

This diagram shows the ranges:

Number of Bits In Four-Digit Decimal Integers

Number of Bits In Four-Digit Decimal Integers

Minimum Number of Bits in a d-Digit Integer

The minimum number of bits required for a d-digit integer is computed simply by using the specific number formula on the minimum d-digit value:

bmin = ⌊log2(10d-1)⌋ + 1

We can make this a more efficient computation by using the logarithmic identity loga(xy) = y·loga(x):

bmin = ⌊log2(10d-1)⌋ + 1 = ⌊(d-1)·log2(10)⌋ + 1

In this form, we take the logarithm of a small constant instead of a large variable.

Since we are dealing with powers of ten we can use the ceiling function here (as long as d > 1); there is no positive power of ten that is also a power of two. Here’s the equivalent formula:

bmin = ⌈log2(10d-1)⌉ = ⌈(d-1)·log2(10)⌉

Maximum Number of Bits in a d-Digit Integer

The maximum number of bits required for a d-digit integer is computed simply by using the specific number formula on the maximum d-digit value:

bmax = ⌊log2(10d – 1)⌋ + 1

We can’t make the same simplification as for the minimum value, at least not on the face of it. But notice that ⌊log2(10d – 1)⌋ = ⌊log2(10d)⌋, since a power of ten and that power of ten minus one are both in the same power of two range. (A power of ten minus one cannot be a power of two — it’s odd). This allows us to use this more computationally efficient formula to the same effect:

bmax = ⌊log2(10d)⌋ + 1 = ⌊d·log2(10)⌋ + 1

And again, for d > 1, we can use the ceiling function instead:

bmax = ⌈d·log2(10)⌉

Average Number of Bits in a d-Digit Integer

The average number of bits required for a d-digit integer is the total number of bits required to represent all d-digit integers divided by the number of d-digit integers. For our example, the average is

bavg = (24·10 + 1024·11 + 2048·12 + 4096·13 + 1808·14)/9000 ≈ 12.74

Computing The Formulas

Of the above formulas, these two — in these forms — are the most commonly used:

  • bspec = ⌊log2(n)⌋ + 1
  • bmax = ⌈d·log2(10)⌉

How do you compute them?

First we have to figure out how to take the base-2 logarithm of a number. Many programming environments do not have a base-2 logarithm function. You can deal with that by doing a change of base:

log2(n) = loga(n)/loga(2)

a’ could represent any base; for example, base e, the natural logarithm. For simplicity, I’ll drop the ‘a’ and refer to the logarithm function generically as log(n):

log2(n) = log(n)/log(2)

Computing bspec

Let’s restate the formula in the form you would most likely enter it in a computer:

bspec = floor(log(n)/log(2)) + 1

For example, the decimal integer 1,997,443,410 has floor(log(1997443410)/log(2)) + 1 = 31 bits.

You have to be careful when computing logarithms; floating-point inaccuracies could cause an incorrect result, particularly at power-of-two boundaries.

(If you are using a language like C you could avoid change of base — and improve performance and accuracy — by computing the floor of the base-2 logarithm using “Bit Twiddling Hacks”.)

For very large numbers, you’ll need arbitrary-precision arithmetic. I use PARI/GP, for example.

Computing bmax

Let’s restate the formula for computer evaluation:

bmax = ceil(d*(log(10)/log(2)))

(The parentheses around the division are unnecessary; I just like thinking of log(10)/log(2) as a separate constant.)

log(10)/log(2), to 17 digits, is 3.3219280948873623. People commonly round this to 3.32, leading to this simple formula:

bmax = ceil(d*3.32)

For example, a 16-digit decimal integer requires up to ceil(16*3.32) = 54 bits.

You have to be careful with this though; for example, ceil(25*3.32) = 83 (since 25*3.32 = 83), but 25-digit integers require 84 bits. You need to specify the constant with more precision to get the correct result. (Here’s one place where this error is made.)

By Rick Regan (Copyright © 2013 Exploring Binary)

Number of Bits in a Decimal Integer

Ratio of Bits to Decimal Digits

$
0
0

Excluding 0 and 1, it takes more digits to express an integer in binary than in decimal. How many more? The commonly given answer is log2(10) times more, or about 3.32 times more. But this is misleading; the ratio actually depends on the specific integer. So where does ‘log2(10) bits per digit’ come from? It’s a theoretical limit, a value that’s approached only as integers grow large. I’ll show you how to derive it.

Bits Per Digit Varies with the Integer's Value

Bits Per Digit Varies with the Integer's Value

Bits/Digit

To represent an integer n in binary, \mbox{\footnotesize{\displaystyle{\lfloor log_{2}(n)\rfloor + 1}}} bits are required; to represent an integer n in decimal, \mbox{\footnotesize{\displaystyle{\lfloor log_{10}(n)\rfloor + 1}}} decimal digits are required. The ratio of bits to digits is thus

\mbox{\footnotesize{\displaystyle{\frac{\lfloor log_{2}(n)\rfloor + 1}{\lfloor log_{10}(n)\rfloor + 1}}}}

The graph above shows this ratio for n equal 0 through 130. As expected, the ratio varies; it zig-zags, changing at power of two and power of ten boundaries. When you cross a power of two, the number of bits goes up, so the ratio goes up; when you cross a power of ten, the number of decimal digits goes up, so the ratio goes down. This variation continues forever — but does the ratio ever converge? Let’s take a look.

Evidence That the Ratio Converges to log2(10)

First let’s compute the ratio for a few small integers (I used PARI/GP to compute them):

Bits Per Digit (Examples 1)
Decimal Number Ratio Bits Per Digit
1 1/1 1
3 2/1 2
8 4/1 4
30 5/2 2.5
780 10/3 approx 3.333
2012 11/4 2.75

That didn’t tell us much; let’s try bigger numbers:

Bits Per Digit (Examples 2)
Decimal Number Ratio Bits Per Digit
19,888,377 25/8 3.125
14,578,757,201 34/11 approx 3.091
98,456,378,461,883 47/14 approx 3.357

Interesting. Those are all over 3.0. Let’s try even bigger numbers (for simplicity I’ll switch to just using powers of ten):

Bits Per Digit (Examples 3)
Decimal Number Ratio Bits Per Digit
1050 167/51 approx 3.275
1060 200/61 approx 3.279
10120 399/121 approx 3.298
10520 1729/521 approx 3.317
1020000 66439/20001 approx 3.322
101000000 3321929/1000001 approx 3.322
1010000000 33219281/10000001 approx 3.322

Now that looks like it’s converging (at least to 3 places). It turns out it does converge — I’ll prove it.

Proof That the Ratio Converges to log2(10)

(My proof is adapted from these two proofs: Appendix O: “The Ratio of Decimal To Binary Digits” [sic] from Gerald R. Rising’s book “Inside Your Calculator”, and “Fun With Math Volume 2” by Peter M. Maurer.)

We want to show what happens to the ratio as the integers n get bigger. In calculus terms, we are looking for its limit, which is shown with the limit notation, \mbox{\footnotesize{\displaystyle{\lim_{n\to\infty}}}}. This is what we want to find:

\mbox{\footnotesize{\displaystyle{\lim_{n\to\infty}\frac{\lfloor log_{2}(n)\rfloor + 1}{\lfloor log_{10}(n)\rfloor + 1}}}}

The floor notation makes this hard to manipulate. Fortunately, we can just get rid of it — the fractional part of the logarithms become insignificant as n grows large:

\mbox{\footnotesize{\displaystyle{\lim_{n\to\infty}\frac{log_{2}(n) + 1}{log_{10}(n) + 1}}}}

Similarly, we can remove the ‘+ 1′ from the numerator and denominator, since that becomes insignificant as well:

\mbox{\footnotesize{\displaystyle{\lim_{n\to\infty}\frac{log_{2}(n)}{log_{10}(n)}}}}

Now we have something we can work with. Let’s change the base of one of the logarithms so all will be in the same base; let’s chose the denominator:

\mbox{\footnotesize{\displaystyle{\lim_{n\to\infty}\frac{log_{2}(n)} {\left(\frac{log_{2}(n)}{log_{2}(10)}\right)}}}}

This simplifies to

\mbox{\footnotesize{\displaystyle{\lim_{n\to\infty}log_{2}(10)}}}

But notice that n is gone, so there’s no need for the limit notation. This means the limit reduces to this constant:

\mbox{\footnotesize{\displaystyle{log_{2}(10) \approx 3.32}}}

This says, as n grows large, there are approximately 3.32 times as many bits as there are decimal digits. (This doesn’t mean that each decimal digit requires approximately 3.32 bits; it’s just an average across all digits.)

The Minimum and Maximum Ratios

If you look at the graph you’ll see a ratio of one for integers 0 and 1. This is the minimum ratio, since for all other integers, more bits than decimal digits are required. How about the maximum ratio? The graph shows a ratio of four, for integers 8 and 9. Is four the maximum? Does it occur anywhere else? The answers are “yes it is the maximum” and “no it does not occur anywhere else”, but I don’t have a proof. Any takers? (Update: I had one — see the comments below.)

Binary Vs. Octal and Hexadecimal

You can apply the above analysis to representations in any pair of bases. How about the ratio of bits to octal digits? This works out to be \mbox{\footnotesize{\displaystyle{log_{2}(8) = 3}}}. Similarly, the ratio of bits to hexadecimal digits is \mbox{\footnotesize{\displaystyle{log_{2}(16) = 4}}}. Of course, this is not surprising, since everyone “knows” there are 3 bits per octal digit and 4 bits per hexadecimal digit. But remember that I’m talking about pure mathematical representations, not fixed-sized computer representations with explicit leading zeros. For example, 17 octal = 1111 binary, a ratio of 4/2 = 2; 1f hexadecimal = 11111 binary, a ratio of 5/2 = 2.5.

By Rick Regan (Copyright © 2013 Exploring Binary)

Ratio of Bits to Decimal Digits

Number of Decimal Digits In a Binary Integer

$
0
0

This is a companion article to “Number of Bits in a Decimal Integer”

If you have an integer expressed in decimal and want to know how many bits are required to express it in binary, you can perform a simple calculation. If you want to know how many bits are required to express a d-digit decimal integer in binary, you can perform other simple calculations for that.

What if you want to go in the opposite direction, that is, from binary to decimal? There are similar calculations for determining the number of decimal digits required for a specific binary integer or for a b-bit binary integer. I will show you these calculations, which are essentially the inverses of their decimal to binary counterparts.

(As in the companion article, I will be discussing only pure binary and decimal numbers, and dealing with positive integers only.)

Number of Digits in a Specific Binary Integer

If I gave you a binary integer and asked you how many decimal digits it requires, you would convert it to decimal and count the digits. But a computer program does not need to do it that way, since it works in binary arithmetic. It can compute the number of digits directly, without converting the integer to decimal. (Although we’ll be talking about arithmetic operations on binary numbers, I will use decimal numerals in my description.)

A positive integer n has d digits when 10d-1n ≤ 10d – 1. For example, 376 has 3 digits because 100 ≤ 376 ≤ 999, or 102 ≤ 376 ≤ 103 – 1. Said another way, the number of digits in n is the exponent of the smallest power of ten greater than n; mathematically, that’s stated as:

dspec = ⌊log10(n)⌋ + 1

Let’s see how the formula works by looking at its three parts:

  • log10(n) means the logarithm in base 10 of n, which is the exponent to which 10 is raised to get n. For example, log10(376) ≈ 2.575. The presence of a fractional part means n is between powers of ten.
  • x is the floor of x, which is the integer part of x. For example, ⌊2.575⌋ = 2. You can think of ⌊log10(n)⌋ as the exponent of the highest power of ten in the decimal representation of n.
  • + 1 takes the exponent to the next higher power of ten. You can think of this step as accounting for the 100th place of your decimal number, which then gives you its total number of digits. For our example, that’s 2 + 1 = 3.

Don’t be tempted to use the ceiling function — ⌈x⌉, which is the smallest integer greater than or equal to x — to compute the number of digits as such:

dspec = ⌈log10(n)⌉

This fails when n is a power of ten.

Number of Digits in a b-Bit Binary Integer

A positive integer n has b bits when 2b-1n ≤ 2b – 1. How many digits do numbers in this range require? It will vary, depending on whether there is a power of ten between 2b-1 and 2b – 1. If there is no power of ten between them, all b-bit integers will convert to d-digit integers; if there is a power of ten between them, the first part of the b-bit range will require d digits, and the remaining part will require d+1 digits.

For example, 4-bit integers require either one or two digits, because 101 (10) occurs between 23 (8) and 24 – 1 (15). On the other hand, all 5-bit integers require two digits, since no power of ten occurs between 24 (16) and 25 – 1 (31).

I will refer to the two possible values as the minimum and maximum, even though they will be the same most of the time.

Minimum Number of Digits in a b-Bit Integer

The minimum number of digits required for a b-bit integer is computed simply by using the specific number formula on the minimum b-bit value:

dmin = ⌊log10(2b-1)⌋ + 1

We can make this a more efficient computation by using the logarithmic identity loga(xy) = y·loga(x):

dmin = ⌊log10(2b-1)⌋ + 1 = ⌊(b-1)·log10(2)⌋ + 1

In this form, we take the logarithm of a small constant instead of a large variable. (log10(2) is approximately 0.3, but you should compute it to more precision if you want proper results from this formula.)

Since we are dealing with powers of two we can use the ceiling function here (as long as b > 1); there is no positive power of two that is also a power of ten. Here’s the equivalent formula:

dmin = ⌈log10(2b-1)⌉ = ⌈(b-1)·log10(2)⌉

Maximum Number of Digits in a b-Bit Integer

The maximum number of digits required for a b-bit integer is computed simply by using the specific number formula on the maximum b-bit value:

dmax = ⌊log10(2b – 1)⌋ + 1

We can’t make the same simplification as for the minimum value, at least not on the face of it. But notice that ⌊log10(2b – 1)⌋ = ⌊log10(2b)⌋, since a power of two and that power of two minus one are both in the same power of ten range. (A power of two minus one cannot be a power of ten — it’s odd). This allows us to use this more computationally efficient formula to the same effect:

dmax = ⌊log10(2b)⌋ + 1 = ⌊b·log10(2)⌋ + 1

And again, for b > 1, we can use the ceiling function instead:

dmax = ⌈b·log10(2)⌉

Examples

Using the above two formulas, you’ll find that 32-bit integers require 10 digits, and 64-bit integers require either 19 or 20 digits.

Ratio of Decimal Digits to Bits

I showed you that the ratio of bits to digits converges to log2(10). You can derive the expression for the ratio of digits to bits similarly — or you can just recognize that it is the inverse of the bits to digits ratio:

\mbox{\footnotesize{\displaystyle{\frac{1}{log_{2}(10)}}}}

Change the base of the denominator:

\mbox{\footnotesize{\displaystyle{\frac{1}{\left(\frac{log_{10}(10)}{log_{10}(2)}\right)}}}}

Replace log10(10) with 1:

\mbox{\footnotesize{\displaystyle{\frac{1}{\left(\frac{1}{log_{10}(2)}\right)}}}}

Simplify:

\mbox{\footnotesize{\displaystyle{log_{10}(2)}}}

This means there are approximately 0.3 digits per bit.

By Rick Regan (Copyright © 2013 Exploring Binary)

Number of Decimal Digits In a Binary Integer

Hour of Code: Binary Numbers and Binary Addition

$
0
0

I want to contribute to the Hour of Code event happening now during Computer Science Education Week.

I don’t write about computer programming, but I do write extensively about how computers work — in particular, about how they do arithmetic with binary numbers. For your “hour of code” I’d like to introduce you to binary numbers and binary addition. I’ve selected several of my articles for you to read, and I’ve written some exercises you can try on my online calculators.

Binary Numbers

I’ve taught binary numbers to first graders, I’ve taught binary numbers to third graders, and I’ve taught binary numbers to adults. Read those articles and then try these problems:

  1. Convert 45 to binary.
  2. Convert 1001101 to decimal.

Use my decimal/binary converter to check your answers.

Binary Addition

Read my article on binary addition, and then check out my article on the Binary Marble Adding Machine to see it in action. When you are done reading, try these problems:

  1. Add the binary numbers 111 and 110.
  2. Add the binary numbers 1011 and 101.

Use my binary calculator to check your answers.

(Don’t cheat and convert those numbers to decimal first and then add them — although that is a good way to check your work.)

If You Have More Than An Hour…

See what binary numbers look like and what binary numbers sound like.

By Rick Regan (Copyright © 2014 Exploring Binary)

Hour of Code: Binary Numbers and Binary Addition

My Fretlight Guitar As a Binary Clock

$
0
0

With a little research and some USB tracing, I wrote a Windows program — and an Android app — that turns my Fretlight guitar into a BCD mode binary clock!

http://www.exploringbinary.com/wp-content/uploads/FretlightClock.gif

My Fretlight BCD Clock (click image for video)

What Is a Fretlight Guitar?

A Fretlight guitar is a teaching aid for guitarists. It has LEDs embedded in the fretboard. The LEDs are controlled by software on a computer, which is connected to the guitar through a USB cable. The software lights the LEDs to show scales, chords, and songs. Check out this demo if you want to learn more about it.

Why Did I Turn It Into a Binary Clock?

I wanted to know the guitar’s API because I thought it would be cool to control it (not that I knew what I wanted to do with it). When searching I found demos of unconventional uses of the Fretlight: the LED Fretboard Light Show and Conway’s Game of Life on FretLight Guitar. I immediately thought of a binary clock, realizing the six columns of LEDs were a perfect match.

http://www.exploringbinary.com/wp-content/uploads/BCDClock.png

My Real BCD Clock

Researching The Fretlight Interface

Optek Music Systems has a Fretlight SDK that’s available by application, but I found open source software that implemented interfaces: Fretlight Animator (the code behind “Conway’s Game of Life”) and TuxGuitar Light Plugin. Fretlight Animator is written in C#, but I wanted something in C++. Nonetheless, the code was well documented, so I had all that I needed to write my own implementation. TuxGuitar Light Plugin, written in Java, was also a good reference, confirming what I learned from Fretlight Animator.

To verify everything, I decided to “sniff” the USB traffic to my guitar. I wrote a “song” in Guitar Pro 6 to play all 132 notes on the guitar in sequence; here is a screenshot of the first few lines:

http://www.exploringbinary.com/wp-content/uploads/Fretlight-USB-trace.png

First Page of My Guitar Pro “Song” I Wrote to Map the LEDs

(If you are not familiar with guitar tablature, the lines correspond to the six guitar strings, with the thick string at the bottom and thin string at the top. The numbers are the frets, with fret 0 meaning the open string.)

The USB traffic confirmed what was encoded in Fretlight Animator and TuxGuitar.

The Fretlight Interface

The Fretlight is a simple USB HID. The host controls the status of the LEDs by sending reports to the guitar’s interrupt OUT endpoint. Each report is 8 bytes, with a one-byte report ID (0) and a 7-byte packet. Each packet contains a one-byte packet ID and 6 bytes of LED data. Each LED is specified by one bit: a 1 turns the LED on, and a 0 turns the LED off. With 48 bits per packet, you need three packets to specify the status of all 132 LEDs.

Packet ID 1 controls the LEDs in frets 0 through 7, packet ID 2 controls the LEDs in frets 8 through 15, and packet ID 3 controls the LEDs in frets 16 through 21. Each bit in each packet corresponds to a unique combination of fret and string. Fret numbers range from 0-21, and string numbers range from 1-6, with 1 being the high E (thinnest string). Here is the layout of the LEDs, with ‘f’ standing for fret, and ‘s’ standing for string:

          bit 7  bit 6  bit 5  bit 4  bit 3  bit 2  bit 1  bit 0
Packet ID 1
  Byte 0: f6s5   f6s6   f7s1   f7s2   f7s3   f7s4   f7s5   f7s6
  Byte 1: f5s3   f5s4   f5s5   f5s6   f6s1   f6s2   f6s3   f6s4
  Byte 2: f4s1   f4s2   f4s3   f4s4   f4s5   f4s6   f5s1   f5s2
  Byte 3: f2s5   f2s6   f3s1   f3s2   f3s3   f3s4   f3s5   f3s6
  Byte 4: f1s3   f1s4   f1s5   f1s6   f2s1   f2s2   f2s3   f2s4
  Byte 5: f0s1   f0s2   f0s3   f0s4   f0s5   f0s6   f1s1   f1s2
  Byte 6: (0x01)

Packet ID 2
  Byte 0: f14s5  f14s6  f15s1  f15s2  f15s3  f15s4  f15s5  f15s6
  Byte 1: f13s3  f13s4  f13s5  f13s6  f14s1  f14s2  f14s3  f14s4
  Byte 2: f12s1  f12s2  f12s3  f12s4  f12s5  f12s6  f13s1  f13s2
  Byte 3: f10s5  f10s6  f11s1  f11s2  f11s3  f11s4  f11s5  f11s6
  Byte 4: f9s3   f9s4   f9s5   f9s6   f10s1  f10s2  f10s3  f10s4
  Byte 5: f8s1   f8s2   f8s3   f8s4   f8s5   f8s6   f9s1   f9s2
  Byte 6: (0x02)

Packet ID 3
  Byte 0: xxxxx  xxxxx  xxxxx  xxxxx  xxxxx  xxxxx  xxxxx  xxxxx
  Byte 1: f21s3  f21s4  f21s5  f21s6  xxxxx  xxxxx  xxxxx  xxxxx
  Byte 2: f20s1  f20s2  f20s3  f20s4  f20s5  f20s6  f21s1  f21s2
  Byte 3: f18s5  f18s6  f19s1  f19s2  f19s3  f19s4  f19s5  f19s6
  Byte 4: f17s3  f17s4  f17s5  f17s6  f18s1  f18s2  f18s3  f18s4
  Byte 5: f16s1  f16s2  f16s3  f16s4  f16s5  f16s6  f17s1  f17s2
  Byte 6: (0x03)

(The unused bits in packet ID 3 are marked with ‘x’s.)

Overview of My Windows Code

I wrote my program in Visual C++ (Visual Studio 2013). I used hidapi as my USB API because it was extremely simple (I turned to it after trying to wade through Microsoft’s HID examples.) I created a project, included files hidapi.h and hid.c, and changed a few compile and link options.

I used calls hid_init(), hid_open(), hid_write(), hid_close(), and hid_exit(). I used hid_open() to open the Fretlight HID, using its vendor ID (0x0925) and product ID (0x2000). (I don’t know why the vendor ID is 0x0925 — that is assigned to Lakeview Research!). I used hid_write() to send packets to the guitar (hid_write() automatically knew to send to the guitar’s interrupt OUT endpoint).

I initialized local variables to represent the current time on my computer, and then set a one second timer. Each time the timer popped I incremented the time, created the packet (packet ID 3), and sent it to the guitar. I used 19 LEDs: f21s6, f18s5, f19s5, f20s5, f21s5, f19s4, f20s4, f21s4, f18s3, f19s3, f20s3, f21s3, f19s2, f20s2, f21s2, f18s1, f19s1, f20s1, and f21s1.

I picked those frets for several reasons:

  • The LEDs are spaced about as closely as on my real binary clock.
  • The clock is easier to read being up against the last fret (there can’t be any hidden “off” LEDs below it).
  • The LEDs are all in the same packet.

I only implemented BCD mode, and only for 12-hour time.

Overview of My Android Code

After writing and debugging my Windows program I wrote an equivalent Android app to run the Fretlight as a binary clock. I wrote it in Java, using Android Studio. I used the Android USB Host API, classes UsbManager, UsbDevice, UsbInterface, UsbEndpoint, and UsbDeviceConnection. I used the bulkTransfer() method of the UsbDeviceConnection class to send HID packets to the guitar. (I modeled my USB code on the USB HID Terminal app.)

To use an Android device as a USB host, it must support USB OTG; this support is in Android 3.1 and higher. You also need a female USB to male micro USB adapter to connect the Fretlight cable to the device. When writing the app, I enabled wireless debugging, since the device’s USB slot was connected to the guitar.

USB to Micro USB Adapter Connected to the Fretlight Cable

On Reflective Fret Markers

The Fretlight has reflective, circular, LED-sized fret markers, which is a poor design; sometimes they look like a lit LED! See how that plays out in my binary clock by watching the last few seconds of my video (watch when the time turns 10:30:00).

By Rick Regan (Copyright © 2014 Exploring Binary)

My Fretlight Guitar As a Binary Clock

My Fretlight Guitar Binary Clock: Raspberry Pi Edition

$
0
0

I’ve previously written a Windows program (in C++) and an Android app (in Java) to turn my Fretlight guitar into a binary clock. I’ve now written a Python program to do the same, running under Raspbian Linux on a Raspberry Pi computer. I will show you the code and tell you how to run it.

http://www.exploringbinary.com/wp-content/uploads/Fretclock.RaspberryPi.png

My Fretlight BCD Clock, Run by a Raspberry Pi (Time shown: 7:09:26)

Turning the Fretlight Guitar into a Binary Clock

The Fretlight guitar is a teaching aid for guitarists. It connects to a computer through a USB cable, and acts as a USB HID. Software on the computer sends it data that tells it which of its 132 LEDs to light, indicating proper placement of your fingers.

I co-opted the interface and turned my Fretlight into a BCD mode binary clock. I had done this with Windows and Android programs, and now I have done it with a Python program — running on the Raspberry Pi.

(See “My Fretlight Guitar As a Binary Clock” for more background and for the USB communication details.)

fretclock.py

I wrote a program, fretclock.py, to implement my Fretlight clock in Python. I created a class called FretlightBinaryClock that has two “public” methods, start() and stop(). start() activates the clock, which entails opening the Fretlight USB device, getting the current time from the system, and displaying the updated time every second. stop() deactivates the clock, turning off all LEDs and releasing the device.

For USB communication, I use PyUSB, a USB library for Python. PyUSB itself requires a backend USB library, for which I use libusb.

Here is the code:

# fretclock.py: Rick Regan, http://www.exploringbinary.com/, 1/4/16
#   BCD mode (standard time only) binary clock represented on the Fretlight Guitar
#
#   For details see http://www.exploringbinary.com/my-fretlight-guitar-as-a-binary-clock/
#    and http://www.exploringbinary.com/my-fretlight-guitar-binary-clock-raspberry-pi-edition/
#
# To install PyUSB (and required backend, e.g., libusb):
#     sudo apt-get install libusb-1.0-0-dev
#     sudo pip install --pre pyusb
#
# To run:
#    sudo date -s "4 Jan 2016 10:32:00" (Set current date and time)
#    sudo python fretclock.py
#
# To stop: ctrl-c
#
# Credits:
#     PyUSB calls taken from https://github.com/walac/pyusb/blob/master/docs/tutorial.rst
#      and http://stackoverflow.com/questions/12542799/communication-with-the-usb-device-in-python

import usb.core
import usb.util
import time
import datetime
import signal
import sys

def _signal_handler(signal, frame):
    fretclock.stop()
    sys.exit(0)

class FretlightBinaryClock:

    PACKET_LEN = 7 #Number of bytes in a Fretlight USB HID packet

    def __init__(self):
        self.fretlight = 0
        self.cfg = 0
        self.intf = 0
        self.ep = 0
        self.hour = 0
        self.minute = 0
        self.second = 0
        self.packet = bytearray([0] * FretlightBinaryClock.PACKET_LEN)
        self.packet[6] = 0x03 # All LEDS are in packet 3                        

    def _open_fretlight(self):
        self.fretlight = usb.core.find(idVendor=0x0925, idProduct=0x2000) # Open the Fretlight Guitar device (Vendor ID, product ID)

        if self.fretlight is None:
            raise ValueError('Fretlight Guitar not found')

        if self.fretlight.is_kernel_driver_active(0):
            # This will happen once after each time the Fretlight is attached -- it must be detached so we can control it ourselves
            self.fretlight.detach_kernel_driver(0)

        self.fretlight.set_configuration() # Set active configuration (no arguments means the first configuration is actived)

        self.cfg = self.fretlight.get_active_configuration() # Get active configuration
        self.intf = self.cfg[(0,0)] # Get interface

        self.ep = usb.util.find_descriptor(
            self.intf,
            # match the first OUT endpoint
            custom_match = \
            lambda e: \
                usb.util.endpoint_direction(e.bEndpointAddress) == \
                usb.util.ENDPOINT_OUT) # Get endpoint (interrupt OUT endpoint)

        if self.ep is None:
            raise ValueError('Endpoint not found')

    def _leds_off(self):
        self.packet[0] = 0
        self.packet[1] = 0
        self.packet[2] = 0
        self.packet[3] = 0
        self.packet[4] = 0
        self.packet[5] = 0
        self._send_report()

    def _init_clock(self):
        #Initialize from system clock
        self.hour = datetime.datetime.now().time().hour
        if (self.hour > 12):
            self.hour -= 12 # Convert from military to standard
        self.minute = datetime.datetime.now().time().minute
        self.second = datetime.datetime.now().time().second

    def _increment_clock(self):
        self.second += 1
        if (self.second == 60):
            self.second = 0
            self.minute += 1
            if (self.minute == 60):
                self.minute = 0
                self.hour += 1
                if (self.hour == 13):
                    self.hour = 1

    def _send_report(self):
        # Report should begin with a 0 byte followed by the packet, but for some reason with PyUSB, it won't work if you send the 0 
        report = self.packet             
        self.ep.write(report) # Write the data to the Fretlight

    def _create_packet(self):
        # Break time into BCD digits: h1,h2 / m1, m2 / s1,s2

        # Get the two digits of the hour
        h1 = self.hour / 10
        h2 = self.hour % 10

        # Get the two digits of the minute
        m1 = self.minute / 10
        m2 = self.minute % 10
        
        # Get the two digits of the second
        s1 = self.second / 10
        s2 = self.second % 10

        # Set the appropriate LEDs
        # h1 (range: 0-1)
        if (h1 & 1): # LED at fret 21, string 6
            self.packet[1] |= 0x10 # Turn on 
        else:
            self.packet[1] &= ~0x10 # Turn off

        # h2 (range: 0-9)
        if (h2 & 8): # LED at fret 18, string 5
            self.packet[3] |= 0x80 # Turn on 
        else:
            self.packet[3] &= ~0x80 # Turn off

        if (h2 & 4): # LED at fret 19, string 5
            self.packet[3] |= 0x02 # Turn on 
        else:
            self.packet[3] &= ~0x02 # Turn off

        if (h2 & 2): # LED at fret 20, string 5
            self.packet[2] |= 0x08 # Turn on 
        else:
            self.packet[2] &= ~0x08 # Turn off

        if (h2 & 1): # LED at fret 21, string 5
            self.packet[1] |= 0x20 # Turn on 
        else:
            self.packet[1] &= ~0x20 # Turn off

        # m1 (range: 0-5)
        if (m1 & 4): # LED at fret 19, string 4
            self.packet[3] |= 0x04 # Turn on 
        else:
            self.packet[3] &= ~0x04 # Turn off

        if (m1 & 2): # LED at fret 20, string 4
            self.packet[2] |= 0x10 # Turn on 
        else:
            self.packet[2] &= ~0x10 # Turn off

        if (m1 & 1): # LED at fret 21, string 4
            self.packet[1] |= 0x40 # Turn on 
        else:
            self.packet[1] &= ~0x40 # Turn off

        # m2 (range: 0-9)
        if (m2 & 8): # LED at fret 18, string 3
            self.packet[4] |= 0x02 # Turn on 
        else:
            self.packet[4] &= ~0x02 # Turn off

        if (m2 & 4): # LED at fret 19, string 3
            self.packet[3] |= 0x08 # Turn on 
        else:
            self.packet[3] &= ~0x08 # Turn off

        if (m2 & 2): # LED at fret 20, string 3
            self.packet[2] |= 0x20 # Turn on 
        else:
            self.packet[2] &= ~0x20 # Turn off

        if (m2 & 1): # LED at fret 21, string 3
            self.packet[1] |= 0x80 # Turn on 
        else:
            self.packet[1] &= ~0x80 # Turn off

        # s1 (range: 0-5)
        if (s1 & 4): # LED at fret 19, string 2
            self.packet[3] |= 0x10 # Turn on 
        else:
            self.packet[3] &= ~0x10 # Turn off

        if (s1 & 2): # LED at fret 20, string 2
            self.packet[2] |= 0x40 # Turn on 
        else:
            self.packet[2] &= ~0x40 # Turn off

        if (s1 & 1): # LED at fret 21, string 2
            self.packet[2] |= 0x01 # Turn on 
        else:
            self.packet[2] &= ~0x01 # Turn off
 
        # s2 (range: 0-9)
        if (s2 & 8): # LED at fret 18, string 1
            self.packet[4] |= 0x08 # Turn on 
        else:
            self.packet[4] &= ~0x08 # Turn off

        if (s2 & 4): # LED at fret 19, string 1
            self.packet[3] |= 0x20 # Turn on 
        else:
            self.packet[3] &= ~0x20 # Turn off

        if (s2 & 2): # LED at fret 20, string 1
            self.packet[2] |= 0x80 # Turn on 
        else:
            self.packet[2] &= ~0x80 # Turn off

        if (s2 & 1): # LED at fret 21, string 1
            self.packet[2] |= 0x02 # Turn on 
        else:
            self.packet[2] &= ~0x02 # Turn off

    def _update(self):
        self._increment_clock()
        self._create_packet()
        self._send_report()

    def _timer_loop(self):
        while True:
           time_begin = time.time()
           self._update()
           time_end = time.time()
           time_elapsed = time_end - time_begin
           time.sleep(1.0-time_elapsed) # Delay for 1 second, less overhead to this point

    def _set_signal_handler(self):
        signal.signal(signal.SIGINT, _signal_handler)

    def start(self):
        print ("Starting fretclock")
        self._set_signal_handler()
        self._open_fretlight()
        self._leds_off()
        self._init_clock()
        self._timer_loop()
  
    def stop(self):
        print ("Stopping fretclock")
        self._leds_off()
        usb.util.dispose_resources(self.fretlight) 

fretclock = FretlightBinaryClock()
fretclock.start()

Comments

This is the first real Python program I have written. In the time I allotted to this project, I did my best to research and follow Python’s coding conventions (please comment if you have suggestions for improvement). My goal was to explore my new Raspberry Pi, using the recommended language. (I kind of cheated though, so as not to take on too much new stuff at once: I did an initial implementation in C, which was a straightforward port of my Windows C++ code.)

As for the PyUSB API, I could not find a guide detailing all its functions. I just copied the code from this tutorial, and added a few lines of code from this Stack Overflow answer. The code works inasmuch as I tested it, but I don’t know how robust it is. I also don’t understand it well enough to explain, for example, why I had to write the packet directly to the endpoint instead of wrapping it in a USB report (like I did in my C, C++, and Java versions).

Running It On the Raspberry Pi

You must first put an image of Raspbian on the micro SD card; I used Raspbian Jessie. Insert the card in the Pi and power it on — it will boot right up to the graphical desktop. From there, open a terminal window and do the following (as necessary):

Install the USB libraries (the Pi needs to be connected to the Internet for this step):

sudo apt-get install libusb-1.0-0-dev
sudo pip install --pre pyusb

Set the system time (the Pi has no built-in real-time clock); for example:

sudo date -s "4 Jan 2016 10:32:00"

Start the clock:

sudo python fretclock.py

(‘sudo’ is required; otherwise, access to the Fretlight is denied with this message: usb.core.USBError: [Errno 13] Access denied (insufficient permissions))

Stop the clock:

ctrl-c

On my Pi, I observed that the clock loses about 3-4 seconds per hour. I don’t know if this is my code, Python’s sleep command, or the lack of “real-timeness” of the Pi. For my purposes, this is acceptable.

This code should run on any Linux, not just Raspbian. (I also ran it on Ubuntu.)

Comments

When I started this project I wasn’t sure if the Pi would have enough power for itself and the Fretlight. Apparently it does.

Ideally, you would run this code without the Pi hooked up to a monitor, so that you could just plug in the Fretlight and power up the Pi. (You would have the program set to start up at boot.) However, since there is no real-time clock on the Pi, you need to interact with it first to set the time.

To see the Fretlight binary clock in action, check out my video (the video is of the clock running under Windows, but it looks the same when running the Python code on the Pi).

By Rick Regan (Copyright © 2016 Exploring Binary)

My Fretlight Guitar Binary Clock: Raspberry Pi Edition


Binary Numbers Haiku (by ChatGPT)

$
0
0

Continuing with my recent conversation with ChatGPT I thought I’d ask it if it could write haiku about binary numbers, like I have:

Rick responds to ChatGPT ‘Write a haiku about binary numbers’ and ChatGPT answers

Nice, but I was looking for the 5/7/5 syllable format (this is 6/8/5), so I asked for that specifically:


Rick responds to ChatGPT ‘Write a haiku about binary numbers. Please follow the format of five, seven, and five syllables.’ and ChatGPT answers

Oddly, that was worse in terms of format (5/9/5). I tried again with the original, shorter prompt, and then for some reason it was able to crank out four in a row of the desired format:

ChatGPT responds with a 5/7/5 haiku

ChatGPT responds with another 5/7/5 haiku

ChatGPT responds with another 5/7/5 haiku

ChatGPT responds with another 5/7/5 haiku

Pretty impressive! The first of the four is my favorite (plus it is number-centric, like I asked).

The post Binary Numbers Haiku (by ChatGPT) first appeared on Exploring Binary.

ChatGPT Writes Decent Code For Binary to Decimal Conversion

$
0
0

OK, enough just playing around with ChatGPT; let’s see if it can write some code:

Rick tells ChatGPT ‘Write Kotlin code to convert a binary number represented as a string to base 10’ and ChatGPT answers
Part two of Chat GPT's answer


(The line that got cut off in the screenshot of the second solution is

decimal += (binaryArray[i] - '0') * Math.pow(2.0, (binaryArray.size - 1 - i).toDouble()).toInt()

)

My first observation is that it was smart enough to know that by base 10 I meant decimal, and even named the function binaryToDecimal() as I would have.

The first solution is more clever then I was expecting; it uses the built-in function parseInt() to do the conversion directly. It compiles and runs successfully.

The second solution is along the lines of what I was expecting, although it computes the nonnegative powers of two instead of the more efficient “nested” multiplication by two as I do in function bin2dec_i(). It compiles and runs successfully, although it did have one warning from the IDE about the Math.pow() function: “Should be replaced with Kotlin function. Replace with ‘pow’ function”. I replaced “Math.pow(2.0,…” with “2.0.pow(…” and it got rid of the warning.

I was hoping that it might have generated code to handle arbitrary length integers, like my converters and calculators. I guess I’ll have to be more specific.

Arbitrary Length Integers

Rick tells ChatGPT ‘Write Kotlin code to convert an arbitrary precision binary number represented as a string to base 10’ and ChatGPT answers
Part two of Chat GPT's answer

(The line that got cut off in the screenshot of the second solution is

decimal = decimal.add(bit.multiply(BigInteger.valueOf(2).pow(binaryArray.size - 1 - i)))

)

It decided to use BigInteger, which is what I would have done.

The first solution compiles and runs successfully. It takes the “shortcut” of using BigInteger itself to convert integers to different bases directly.

The second solution does not compile. The compiler complains about valueOf(): “None of the following functions can be called with the arguments supplied.”. But a simple fix — appending .toLong() to (binaryArray[i] – ‘0’) — allowed it to compile and run successfully. It still has the same inefficiencies as the limited-precision solution above though.

Stylistically, it did not use operators for the BigInteger functions to make the code easier to read, like this:

decimal += bit * BigInteger.valueOf(2).pow(binaryArray.size - 1 - i)

When I set out with my query I was really hoping that it would generate code to handle any arbitrary length number, integer or floating-point; let’s add that to the request.

Arbitrary Length Floating-Point

Rick tells ChatGPT ‘Write Kotlin code to convert an arbitrary precision binary floating-point number represented as a string to base 10’ and ChatGPT answers
Part two of Chat GPT's answer

This solution does not compile. (And also has the same warning as above about Math.pow().) Even after fixing the small compiler error (changing “val decimal” to “var decimal”) the code works incorrectly. For the sample test code, it prints 1101.625. It incorrectly converts the integer part, treating it as decimal.

A simple additional fix that gets the sample test running correctly is to add import java.math.BigInteger and to replace

var decimal = BigDecimal(parts[0], MathContext.UNLIMITED)

with

var decimal = BigInteger(parts[0], 2).toBigDecimal()

which is a trick it used in another solution.

But the code still has an error, when the input has no integer part; for example, “.101”. This causes the runtime exception “Zero length BigInteger”.

A simple fix for this is to replace the modified line with this further modified line:

var decimal = (if (parts[0].isEmpty()) BigInteger.ZERO else BigInteger(parts[0], 2)).toBigDecimal()

I tested the new version on this number:

 11101011100010101001000110101111010101011111101111111101011010111011.1110101011010001001001101010101010101010101010101010101011111010101010001011101010101

which gave this correct output, as confirmed by my binary to decimal converter:

 
271560613247152281275.9172538916269938194405650664083933868757033715246596017323099658824503421783447265625


There is one additional problem though. “Math.pow(0.5, i + 1.0)” will produce an incorrect result for binary fractional values that are 1074 bits or more. The smallest negative power of two representable in double-precision binary floating-point is 2-1074. Starting at i = 1074, which means when it computes 2-1075, the power will be 0, due to the underflow.

The final fix is to use the BigInteger pow() function. In keeping with the original style of ChatGPT’s solution, and making the minimum change possible, I replaced

fraction += BigDecimal(bit * Math.pow(0.5, i + 1.0))

with

fraction += bit.toBigDecimal() * BigDecimal.ONE.divide(BigInteger.TWO.pow(i + 1).toBigDecimal())

I tested this with fractional values longer than 1074 bits.

Finally, I was expecting it to use BigIntegers with scaling, not BigDecimal, which is overkill. And it computes the negative powers of two instead of the more efficient “nested” division by two as I do in function bin2dec_f().

Conclusion

I’m not sure what to make of ChatGPT’s coding ability since I only asked it to code a short, well-known algorithm. But for this case I’d say its results are a great starting point, and is easier than searching the Web. On the other hand, searching could open your eyes to other solutions, and to the errors I pointed out.

It’s interesting that ChatGPT wrote decent Kotlin, given that it’s a relatively new language, and considering ChatGPT’s training data is only through 2021. I was also impressed that it printed the code in dark mode, which seems to be what developers prefer.

I wonder: if ChatGPT learned to code by reading others’ code, what happens when it learns from its own code? This sounds like one giant feedback loop converging to incorrect answers. (This is a bigger issue, applying to everything it learns, not just code.)

The post ChatGPT Writes Decent Code For Binary to Decimal Conversion first appeared on Exploring Binary.

Viewing all 17 articles
Browse latest View live