Hey There,
NOTE: There is no revised code in this post.
Let me get going on today's post by thanking everyone everywhere for their off-site comments the past few days, and advising you not to read tomorrow's post. It's going to be boring as @@@@, if this isn't ;)
I've been on-the-air for long enough now, that I'm going to post a "Mission Statement" that addresses the most common complaints I get on other sites and boards regarding this blog. Of course, the number one complaint is about my no-comments policy, but it will be fully explained (in granular detail) tomorrow and a link to it will be set at the top right of this blog for easy reference from that point on. In the meantime, feel free to click on the "Send me a comment" link in the upper right (below the header) corner. That will remain there as well. I've always put my email in every script I've posted, but realize that, when I go on a week long "op-ed" bender, folks probably wonder how they're supposed to contact me. It makes perfect sense. Now that I'm aware that folks are actually reading this blog and want to comment, I'll leave the email address in an easily visible place and stick with my no-comments policy, explained tomorrow or any time you want to read it after that. If I ever get off of Blogspot, I'll open up the comment floodgates (but that's for tomorrow).
Our post, from two days ago, about converting binary numbers to decimal the hard way was either widely misunderstood or its essence just poorly captured by my imagination. I know that most folks who look at a blog post with code in it will jump directly there, without reading the preamble, which is probably where I made my biggest mistake.
My second biggest mistake was to put up C code again (for the 2nd or 3rd time, I think) in an attempt to appeal to folks who were looking to take that next step and forget the mysticism surrounding it. In other words, as stated in the text leading up to the post, the code was imperfect on purpose. Top that off with the fact that I thought my original dumbed down code was too complicated and the fact that it compiled perfectly, even with a few errors in it (according to us humans, not gcc ;) and it caused quite a bit of controversy, if not some outright flaming, over at LXer, a site I like a lot (and in no way mean to defame) because I've been syndicating them since I can't remember when :) I am not, first and foremost, a C programmer by trade, so I can take the criticism (In fact, I welcome it, because it's the weakest language of the programming/scripting languages I know. Plus I've done some contracting gigs at banks and trading firms where I've been verbally assaulted for doing my job exactly correctly. If I didn't have a thick-skin for that sort of informal argument, I'd be working in a different trade by now, or be on my 5th or 6th heart attack ;)
At any point, the resulting fracas made me realize that my tendency to write volumes doesn't necessarily work well in certain types of posts. I try to frame the posts in a certain way so that each highlights a specific (or broad) aspect of itself, sometimes with the code as nothing more than a thin-vehicle to illustrate the point. Of course, if no one reads the prose, that aspect is lost.
This blog, like most blogs and their content, is provided free to anyone who wants to come by and take a look. I look at the whole thing as a learning experience for others as well as myself. I've been asked many times how I can manage to do a post a day, and the answer is "at some cost" - Not everything is as perfect as it would be if I were being paid and could take extra time. That being said, any works published here can be used as the seeds for building something better.
I use Creative Commons licensing so my site doesn't get completely ripped off "for-profit." This site is meant to be free. There will never be a charge. For that reason, although you do have my apologies and I try to maintain a high standard of quality, every once in a while, things I post on here won't be cut-and-paste simple (I even post updates - just do a site-search for "update" or "improved" and you'll find some re-posts with corrections attributed to the gracious reader who was kind enough to take the time and make me aware of a mistake I made, or a better way to get the job done).
I can assure you that every program I put up here either compiled or ran on whatever version of Unix or Linux I was running it on at the time, but I can't guarantee that they all will work on all of them. Therefore, no matter how many more years I remain in this profession and/or how much better I get, it would be ludicrous for me to ever state that I'm the "absolute authority" on anything (which, as far as I know, I never have). I've been a Unix/Linux SysAdmin for about 13 years (starting back when pretty much everyone actually believed Linux would never amount to anything) and lots has changed in that period of time. The fact that I'm not a full time programmer (just check the variety of posts and you'll get a flavour for what I do for a living) should make any reader question the content. And I'm glad that they do. Over the months, I've gained much valuable insight into things I could be doing better and I'm receptive to any criticism as long as it's not off-the-charts insulting or irrational.
That being said, here's a quicker way to convert binary numbers to decimal in the shell, although it defeats the original intent of the two previous posts (which was: trying to make uncomfortable individuals feel comfortable enough to believe they can learn to do this stuff, which they can. And please don't take that the wrong way. I only do this because I'm surrounded every day by talented people who honestly don't have the confidence in themselves or think this-and-that is far beyond their grasp, which it isn't):
host # echo 'ibase=2;11100011'|bc
227
The shortest method I know of, which, at a high-level, involves translation from binary to an ascii representation of a decimal, is to just type a number key ;)
Thank you to everyone who commented on the past few scripts and, rest assured, I'll keep your recommendations in mind and follow them as they seem necessary within the context of each individual post.
And, for those of you who wonder how I can do this every night, it took me 23 minutes to write this post. No code, just passion for writing and the subject matter. It actually takes at least twice as long to submit my work, answer questions on Forums and respond to comments (now :) Although I can't respond to them all 24 hours a day... that would suck the joy right out of this endeavour. Remember; I'm not avoiding you, I just have other things to do :)
Again, if you don't want to switch-off like a narcoleptic, avoid tomorrow's post. It's going to just be a long drawn out listing of my personal policies regarding this blog, along with explanation for each. Snooze... ;)
Best wishes,
, Mike
Thursday, July 17, 2008
The Easy Way To Convert Binary To Decimal
Wednesday, July 16, 2008
Perl and Bash Versions Of Binary To Decimal Conversion Script
Hey There,
As promised, in yesterday's post on converting binary values to decimal in C, today we're going to follow up with straight-up ports to Perl and shell. Actually, they'll be slightly different. If you check yesterday's post, for some reason I left in a variable called "difference" which was a part of the code I mentioned that I had originally written to pad 0's on the left hand side of a binary number less than 8 digits. Actually, it was noticed by an LXer, too, as well as the fact that I didn't specifically initalize "char binnumber" with a value. Whoops :) Special thanks to friends who pointed out that someone had commented on that. Not enough hours in the day to check everywhere. Thanks to the folks at LXer.com for doubling my virtual shame ;) Just kidding.
Anyway, I've mulled it over and I've decided to leave the original post with the error even though it could be fixed with a simple edit. I'm as fallible as the next guy (denying it would be pompous folly) and if I spent the rest of my life doing nothing but cleaning up my mistakes I'd never learn from them or (even worse) miss out on most of the good things life has coming around the bend. It can be a chore just thinking of something to write about once today; writing quick programs can be a real sleep-stealer. But I'm going waaaay off-topic.
Both of today's scripts work exactly as they did in yesterday's post (with the bonus that these programs will know whether your variables are integers or characters just by defining them (No initialization necessary). Please check out that conversion program post for specifics on how the program works, it's purposefully imposed limitations, etc.
Both scripts (Perl and shell -- and I think this is the first time I've ever thrown two scripts into one post, so apologies if the Blogspot code formatting is worse than usual ;) run just like yesterdays code, except I've named them differently. You can, of course, change the names to whatever you want:
host # ./bin2dec.pl
or
host # ./bin2dec.sh
and both produce output that's exactly the same:
host # $ ./bin2dec.pl
8 Digit Binary Number?
10010010
Binary 10010010 equals Decimal 146!
We're not going into an explanation of porting at this point (we're following that on a separate path in our posts on porting between Perl, shell and Awk), but you should be able to see a lot of similarities between the code.
Note that, for today, the Perl script will come first and then the shell script. They should be easy to discern. We'll see... this is my first try at doing a double-script ending. Maybe one day they'll let me do attachments (If the GoogleBot can hear me, I'll gladly pay for that :)
Cheers,
This work is licensed under a
Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License#!/usr/bin/perl
# bin2dec.pl - Convert 8 digit binary numbers
# to decimal numbers
#
# 2008 - Mike Golvach - eggi@comcast.net
#
# Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License
$total = 0;
print "\n8 Digit Binary Number?\n";
chomp($binnumber = (<STDIN>));
@binnumber = split(//, $binnumber);
$length = @binnumber;
if ( $binnumber[7] == 1 ) {
$total += 1;
}
if ( $binnumber[6] == 1 ) {
$total += 2;
}
if ( $binnumber[5] == 1 ) {
$total += 4;
}
if ( $binnumber[4] == 1 ) {
$total += 8;
}
if ( $binnumber[3] == 1 ) {
$total += 16;
}
if ( $binnumber[2] == 1 ) {
$total += 32;
}
if ( $binnumber[1] == 1 ) {
$total += 64;
}
if ( $binnumber[0] == 1 ) {
$total += 128;
}
print "\nBinary $binnumber equals Decimal $total!\n";
exit(0);
#!/bin/bash
# bin2dec.sh - Convert 8 digit binary numbers
# to decimal numbers
#
# 2008 - Mike Golvach - eggi@comcast.net
#
# Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License
total=0
echo -e "\n8 Digit Binary Number?\n"
read number
length=${#number}
set -a binnumber
for x in $(seq 0 $((${#number} - 1)))
do
binnumber[$x]=${number:$x:1}
done
if [ ${binnumber[7]} -eq 1 ]
then
total=$((total + 1))
fi
if [ ${binnumber[6]} -eq 1 ]
then
total=$((total + 2))
fi
if [ ${binnumber[5]} -eq 1 ]
then
total=$((total + 4))
fi
if [ ${binnumber[4]} -eq 1 ]
then
total=$((total + 8))
fi
if [ ${binnumber[3]} -eq 1 ]
then
total=$((total + 16))
fi
if [ ${binnumber[2]} -eq 1 ]
then
total=$((total + 32))
fi
if [ ${binnumber[1]} -eq 1 ]
then
total=$((total + 64))
fi
if [ ${binnumber[0]} -eq 1 ]
then
total=$((total + 128))
fi
echo -e "\nBinary $number equals Decimal $total!\n"
exit 0
, Mike
Tuesday, July 15, 2008
Converting Binary Numbers To Decimal The Hard Way On Linux Or Unix
Hey There,
If you recall a while back, we looked at using Perl's "unpack" function to easily convert binary values to decimal and convert decimal back to binary. Those were both (some folks may consider) relatively sophisticated methods of tackling the problem. Although, once you understand how "unpack" works, the first becomes incredibly simple to use and understand. The other one may always be a little awkward.
Today we're going to look at doing binary to decimal conversion using a less "worldly" method ;) The program we have for you today (and I refer to it as a program since it's written in C) attacks the problem more naturally. And, by naturally, I mean that it should make sense to anyone at its core (assuming they understand the C programming language). The method of execution is not the most efficient, but I think it's the most "human readable." In a future post, we'll definitely convert it to Perl, shell and Awk. And, maybe before then, we'll get to the next part in our ongoing series on Perl, shell and Awk porting. We'll get there eventually. If I didn't have so many different things to write about, I could bore you to tears with that stuff (if I haven't already ;)
Hope you enjoy the program. You can build it easily, using a compiler like gcc in this fashion:
host # gcc -o bin2dec bin2dec.c
and run it just as easily:
host # $ ./bin2dec
8 Digit Binary Number?
10010010 <-- I think there's a subtle homage to Rush in there - just forget about the ending 0 ;)
Binary 10010010 equals Decimal 146!
The only catch, which the executable program will prompt you with, is that (in order to keep it simple) it's limited to 8 digit binary numbers and expects an 8 digit binary number as input. This means that binary 1 would return 128 (10000000) instead of 1 (00000001). Both symptoms can be fixed by adding extra code to pad zeros on the left hand side, but I felt, after seeing the resulting code, that including it would take away from the basic gist of this post, which is that C, Perl, shell and Awk are totally accessible to "anyone" who wants to learn them. I wanted to put something out that looked as little like a completely foreign language as possible. It is my philosophy that anyone can learn how to code and/or use the Linux or Unix Operating System(s).
Of course, if "everyone" loses their irrational "fear of computers" and does start doing this stuff well, I'll end up being a fry-guy at McDonald's in about 10 years ;)
Cheers,
This work is licensed under a
Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License/********************************************
* bin2dec - Convert 8 digit binary numbers *
* to decimal numbers *
* *
* 2008 - Mike Golvach - eggi@comcast.net *
* *
********************************************/
/* Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
main()
{
char binnumber[8];
int length;
int difference;
int total = 0;
printf("\n8 Digit Binary Number?\n");
scanf("%s", &binnumber);
length = strlen(binnumber);
if ( length < 8 ) {
difference = -(length - 8);
}
if ( binnumber[7] == '1' ) {
total = total + 1;
}
if ( binnumber[6] == '1' ) {
total = total + 2;
}
if ( binnumber[5] == '1' ) {
total = total + 4;
}
if ( binnumber[4] == '1' ) {
total = total + 8;
}
if ( binnumber[3] == '1' ) {
total = total + 16;
}
if ( binnumber[2] == '1' ) {
total = total + 32;
}
if ( binnumber[1] == '1' ) {
total = total + 64;
}
if ( binnumber[0] == '1' ) {
total = total + 128;
}
printf("\nBinary %s equals Decimal %d!\n", binnumber, total);
return 0;
}
, Mike
Wednesday, March 19, 2008
Converting Decimal Values To Binary Without Using Unpack
Howdy,
Yesterday we took a look at using Unix or Linux Perl's unpack function to convert binary numbers to decimal. Today we're going to look at doing the opposite conversion ( decimal to binary ) and we're going to do it without using unpack :)
Actually, this script would be a whole lot shorter if we were to use the unpack function, but I wanted to highlight that Perl (and most scripting languages) can be used to achieve whatever ends you need met in any number of ways. Generally, your possibilities are limited only by your imagination (and the most basic rules ;)
To achieve the results we want from today's script, we're taking the input (the decimal number) and breaking it down into an array of binary values. The array that gets produced can be fed to yesterday's script to convert binary back to decimal just to verify, if you want :)
The process of converting the decimal number to a binary one in this script, breaks down (at its most basic level) to using the Perl exponential operator (**) to create a massive array of possible binary values and then using that same exponential math to determine whether each valid binary value is a 0 or a 1, and building the array (the actual answer) from that.
I hope these scripts serve as a halfway decent example of how you can do two almost identical things in two almost completely different ways, and, perhaps, as an incentive to write each of the two scripts (yesterday's and today's) in the manner of the other (Not necessary, and not necessarily fun, but a good exercise nonetheless ;)
Best wishes,
This work is licensed under a
Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License#!/usr/bin/perl
#
# db - Convert decimal values to binary
#
# 2008 - Mike Golvach - eggi@comcast.net
#
# Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License
#
print "Decimal Value:\t";
chomp ($decimal=<stdin>);
$x = 100;
$total = "0";
while ($x != -1) {
$y = 2 ** $x;
$total = $total + $y;
--$x;
}
$a = 100;
$b = 0;
$decbin{$a} = 2 ** $a;
while ($a != -1) {
if ($decimal > $total) {
print "Time to Upgrade, boy!\n";
exit;
}
$decbin{$a} = 2 ** $a;
if ($decimal >= $decbin{$a}) {
$decimal = $decimal - $decbin{$a};
$binarray[$b] = 1;
--$a;
$b++;
} else {
$binarray[$b] = 0;
--$a;
$b++;
}
}
while ($binarray[0] != 1) {
$tmp = shift(@binarray);
$tmp = "0";
--$x;
}
$binarray = join("", @binarray);
print "Binary Number:\t$binarray\n";
, Mike
linux unix internet technology
Tuesday, March 18, 2008
Using Unpack To Convert Binary Values To Decimal
Hey There,
Today's post may seem like a step back for regular readers, but I like to keep this blog accessible, so I've decided to revisited the Perl unpack function to demonstrate how it can be used in one of its simplest forms on either Linux or Unix. A more advanced example can be found in our previous post on taking a look inside the wtmpx file.
The Perl script we're presenting today only consists of one simple unpack function surrounded by a whole bunch of processing code. If certain parts were modularized, this would make a decent simple function in a greater calculator/conversion script.
Notice that when we use the unpack value to convert a binary number, say:
11101110
to the decimal number:
238
all we're really doing is feeding the value (11101110) to the unpack function and telling it to convert the input using a standard template ("C" in this case - which stands for an unsigned character - octet - value). You'll not that we've actually put "C*" to account for an infinitely variable number of unsigned octet character values. If we didn't do this (Just put "C" instead), the unpack function would only process the first character the script fed it, so our original input:
11101110
would translate to this:
1
So, as you can see, in this simple function - unpack("C*", $binary) - the definition of the predefined template value C can make a huge amount of difference. It can also allow you to be as specific as you need to be. For instance - unpack("CC", $binary) - would produce:
3
from the same input. This can also be written as - unpack("C2", $binary) - which will save you a lot of typing if you want to match exactly 245 C's ;)
Hope you find this script useful and that it helps you to get more into Perl's pack and unpack functions. Once you get past the seeming incomprehensibility of the general statements, it all makes sense :)
Cheers,
This work is licensed under a
Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License#!/usr/bin/perl
#
# bd - convert binary numbers to decimal
#
# 2008 - Mike Golvach - eggi@comcast.net
#
# Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License
#
print "Binary Number:\t";
chomp ($binary=<stdin>);
@bitvalue = unpack("C*", $binary);
$bitvalue = @bitvalue;
$substring = $bitvalue - 1;
while ($substring ne -1) {
$number = substr($binary, $substring, 1);
$binarray[$substring] = $number;
--$substring;
}
@decarray = reverse(@binarray);
$exponent = 0;
foreach $subscript (@decarray) {
if ($subscript == 1) {
$subscript = 2 ** $exponent;
} elsif ($subscript == 0) {
$subscript = 0;
} else {
print "Are you sure you know what a Binary Number is?\nMaybe you shouldn't be using this...\n";
exit;
}
$exponent++;
}
$decimal = "0";
foreach $integer (@decarray) {
$decimal += $integer;
}
print "Decimal Value:\t$decimal\n";
exit;
, Mike
linux unix internet technology