A Tale of Two Programs (Java)
A Tale of Two Programs (JavaScript)
// A Tale of Two Programs
// by John P. Spurgeon
//
// This program is intended to help you see and understand
// how bitwise operators work. It also contains a class
// named Assignment3 that you can use to get started on
// programming assignment #3. Pay close attention to the code
// that comprises the classes BitString and Bitwise. Although
// those classes contain several methods, each method is fairly
// easy to understand and use, especially if you have read
// Chapter 1 (Elements of Programming), Chapter 2 (Functions
// and Modules), and Chapter 6 (A Computing Machine) of
// _Computer Science: An Interdisciplinary Approach_ by Robert
// Sedgewick and Kevin Wayne.
/**
* BitString is a colleciton of utility functions that
* operate on or produce a string of bits (1s and 0s).
*/
class BitString {
// Remove leading bits if necessary.
public static String trim(String bits, int maxLength) {
final int indexOfTail = bits.length() - maxLength;
return bits.substring(indexOfTail > 0 ? indexOfTail : 0);
}
// Pad bits with leading zeros if necessary.
public static String pad(String bits, int minLength) {
int qtyToAdd = minLength - bits.length();
while (qtyToAdd-- > 0) {
bits = "0" + bits; // Prepend a leading zero.
}
return bits;
}
// Removes any non-binary digits from the input string.
public static String filter(String digits) {
String bits = "";
final int n = digits.length();
for (int i = 0; i < n; i++) {
char digit = digits.charAt(i);
if (digit == '0' || digit == '1') {
bits += digit;
}
}
return bits;
}
// Pad and trim as necessary to achieve desired length.
public static String fixLength(String bits, int desiredLength) {
final int currentLength = bits.length();
if (currentLength > desiredLength) {
bits = trim(bits, desiredLength);
}
else if (currentLength < desiredLength) {
bits = pad(bits, desiredLength);
}
return bits;
}
// Generate a pseudo-random sequence of bits.
public static String random(int length) {
String bits = "";
while (length-- > 0) {
bits += Math.random() < 0.5 ? "0" : "1";
}
return bits;
}
// Convert a base 10 integer to a string of bits.
public static String fromInt8(byte n) {
return pad(Integer.toUnsignedString(n, 2), 32);
}
public static String fromInt16(short n) {
return pad(Integer.toUnsignedString(n, 2), 32);
}
public static String fromInt32(int n) {
return pad(Integer.toUnsignedString(n, 2), 32);
}
public static String fromInt64(long n) {
return pad(Long.toUnsignedString(n, 2), 64);
}
// Convert a string of bits to a base 10 integer.
public static int toInt32(String bits) {
return Integer.parseUnsignedInt(bits, 2);
}
public static long toInt64(String bits) {
return Long.parseUnsignedLong(bits, 2);
}
}
/**
* Bitwise is a collection of functions that provide
* alternate, more verbose ways of invoking the Java
* operators &, |, ^, ~, >>>, >>, and <<.
*/
class Bitwise {
// And
public static int AND(byte x, byte y) { return x & y; }
public static int AND(short x, short y) { return x & y; }
public static int AND(int x, int y) { return x & y; }
public static long AND(long x, long y) { return x & y; }
// Or
public static int OR(byte x, byte y) { return x | y; }
public static int OR(short x, short y) { return x | y; }
public static int OR(int x, int y) { return x | y; }
public static long OR(long x, long y) { return x | y; }
// Xor (Exclusive Or)
public static int XOR(byte x, byte y) { return x ^ y; }
public static int XOR(short x, short y) { return x ^ y; }
public static int XOR(int x, int y) { return x ^ y; }
public static long XOR(long x, long y) { return x ^ y; }
// Not (a.k.a. Complement)
public static int NOT(byte x) { return ~x; }
public static int NOT(short x) { return ~x; }
public static int NOT(int x) { return ~x; }
public static long NOT(long x) { return ~x; }
// Shift Right Unsigned (a.k.a. Logical Shift Right)
public static int SRU(byte x, int n) { return x >>> n; }
public static int SRU(short x, int n) { return x >>> n; }
public static int SRU(int x, int n) { return x >>> n; }
public static long SRU(long x, int n) { return x >>> n; }
// Shift Right (a.k.a. Arithmetic Shift Right)
public static int SR(byte x, int n) { return x >> n; }
public static int SR(short x, int n) { return x >> n; }
public static int SR(int x, int n) { return x >> n; }
public static long SR(long x, int n) { return x >> n; }
// Shift Left
public static int SL(byte x, int n) { return x << n; }
public static int SL(short x, int n) { return x << n; }
public static int SL(int x, int n) { return x << n; }
public static long SL(long x, int n) { return x << n;}
}
/**
* SomeBits is composed of a functions that demonstrate
* how Java's bitwise operators work and how the classes
* BitString and Bitwise can be used.
*/
class SomeBits {
public static void cannedDemo() {
System.out.println("Canned Demo\n");
final String[] args = {
"32", "random", "1000101",
"AND",
"OR",
"XOR",
"NOT", "y",
"NOT", "x",
"SRU", "x", "8",
"SR", "x", "8",
"SL", "x", "8",
"SRU", "y", "1",
"SL", "y", "1"
};
SomeBits.demo(args);
}
public static void demo(String args[]) {
// Check for the three required command line arguments:
// 1. args[0]: an integer.
// 2. args[1]: the string "random" or a string of bits.
// 3. args[2]: the string "random" or a string of bits.
if (args.length < 3) {
final String help =
" Syntax: n bits|random bits|random [optional args]";
System.out.println(help);
return; // Don't continue without at least 3 arguments.
}
// Constant variables.
final int cmdLineArgsCount = args.length;
final int n = Integer.parseInt(args[0]);
final String xBits = args[1].equals("random") ?
BitString.random(n) : BitString.filter(args[1]);
final String yBits = args[2].equals("random") ?
BitString.random(n) : BitString.filter(args[2]);
final String xBits32 = BitString.fixLength(xBits, 32);
final String yBits32 = BitString.fixLength(yBits, 32);
final int xBase10 = BitString.toInt32(xBits);
final int yBase10 = BitString.toInt32(yBits);
// Non-constant variables.
int zBase10, qtyOperand = 0;
String zBits, opcode, whichBitsOperand = "?";
// Print header information.
System.out.print("Value ");
System.out.print(" Base 2 ");
System.out.println(" Base 10");
System.out.print(" x: " + xBits32);
System.out.println(" (" + xBase10 + ")");
System.out.print(" y: " + yBits32);
System.out.println(" (" + yBase10 + ")");
System.out.println();
// Process optional arguments.
for (int i = 3; i < cmdLineArgsCount; i++) {
// Note the opcode and, if applicable, values of operands.
opcode = args[i];
if (opcode.equals("NOT") || opcode.equals("SRU") ||
opcode.equals("SR") || opcode.equals("SL")) {
i = i + 1;
whichBitsOperand = args[i];
if (!whichBitsOperand.equals("x")) {
whichBitsOperand = "y";
}
}
if (opcode.equals("SRU") || opcode.equals("SR") ||
opcode.equals("SL")) {
i = i + 1;
qtyOperand = Integer.parseInt(args[i]);
}
// Perform the specified operation and print the results.
switch (opcode) {
case "AND":
zBase10 = Bitwise.AND(xBase10, yBase10);
zBits = BitString.fromInt32(zBase10);
System.out.print("AND(x, y): ");
System.out.println(zBits + " (" + zBase10 + ")");
break;
case "OR":
zBase10 = Bitwise.OR(xBase10, yBase10);
zBits = BitString.fromInt32(zBase10);
System.out.print(" OR(x, y): ");
System.out.println(zBits + " (" + zBase10 + ")");
break;
case "XOR":
zBase10 = Bitwise.XOR(xBase10, yBase10);
zBits = BitString.fromInt32(zBase10);
System.out.print("XOR(x, y): ");
System.out.println(zBits + " (" + zBase10 + ")");
break;
case "NOT":
zBase10 = whichBitsOperand.equals("x") ?
Bitwise.NOT(xBase10) : Bitwise.NOT(yBase10);
zBits = BitString.fromInt32(zBase10);
System.out.print(" NOT(" + whichBitsOperand + "): ");
System.out.println(zBits + " (" + zBase10 + ")");
break;
case "SRU":
zBase10 = Bitwise.SRU(
whichBitsOperand.equals("x") ? xBase10 : yBase10,
qtyOperand);
zBits = BitString.fromInt32(zBase10);
System.out.print("SRU(" + whichBitsOperand + ", ");
System.out.print(qtyOperand + "): ");
System.out.println(zBits + " (" + zBase10 + ")");
break;
case "SR":
zBase10 = Bitwise.SR(
whichBitsOperand.equals("x") ? xBase10 : yBase10,
qtyOperand);
zBits = BitString.fromInt32(zBase10);
System.out.print(" SR(" + whichBitsOperand + ", ");
System.out.print(qtyOperand + "): ");
System.out.println(zBits + " (" + zBase10 + ")");
break;
case "SL":
zBase10 = Bitwise.SL(
whichBitsOperand.equals("x") ? xBase10 : yBase10,
qtyOperand);
zBits = BitString.fromInt32(zBase10);
System.out.print(" SL(" + whichBitsOperand + ", ");
System.out.print(qtyOperand + "): ");
System.out.println(zBits + " (" + zBase10 + ")");
break;
}
}
System.out.println(); // Finally, print a new-line character.
}
}
/**
* Assignment3 is an example of a way to get started
* on Assignment #3 if you want to use Java.
*/
class Assignment3 {
/**
* (Describe what compare does here.)
*/
private static int compare(int a, int b) {
int mask = Bitwise.SL(1, 15);
// (Missing code goes here.)
return 0; // (Change this to something else.)
}
/**
* (Describe what getMax does here.)
*/
private static int getMax(String[] args) {
// Use args to create an array of integers.
final int n = args.length;
int[] posInts = new int[n];
for (int i = 0; i < n; i++) {
posInts[i] = Integer.parseInt(args[i]);
}
// (Missing code goes here.)
return 0; // (Change this to something else.)
}
public static int mystery(String[] args) {
return getMax(args);
}
}
/**
* TwoPrograms will execute the program SomeBits.cannedDemo
* if the first command line argument is the string "demo".
* Otherwise, TwoPrograms executes Assignment3.mystery and
* prints the integer value returned by the mystery program.
*/
public class TwoPrograms {
public static void main(String[] args) {
if (args.length > 0 && args[0].equals("demo")) {
SomeBits.cannedDemo();
}
else {
final String[] input = args;
final int output = Assignment3.mystery(input);
System.out.println(output);
}
}
}
Somewhat Related JavaScript