ExposedFloat.java Source code

Java tutorial

Introduction

Here is the source code for ExposedFloat.java

Source

/********************************************************************
    
Copyright (c) 1996 Artima Software Company. All Rights Reserved.
    
 * Permission to use, copy, modify, and distribute this software
 * and its documentation for EVALUATION purposes only
 * is hereby granted provided that this copyright notice
 * appears in all copies. "Evaluation purposes" are any uses which
 * do not constitute the sale, sharing, or redistribution of this
 * software with or to any other persons in any medium.
 *
 * ARTIMA SOFTWARE COMPANY MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT
 * THE SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING
 * BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. ARTIMA SOFTWARE COMPANY
 * SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF
 * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
    
PROJECT:  JavaWorld
MODULE:   Under The Hood
FILE:   ExposedFloat.java
    
AUTHOR:   Bill Venners, August 1996
    
DESCRIPTION:
    
This file contains all the code for the Floating Point Viewer
applet, named Exposed Float, that accompanies the Under The Hood article titled,
"Floating Point Arithmetic".
    
As I developed this applet I had every class in a separate file. I combined
them in one file here to make it easier to download.
    
*********************************************************************/

import java.awt.*;
import java.applet.*;

public class ExposedFloat extends Applet {

    private Label binaryField;
    private Label signField;
    private Label exponentField;
    private Label mantissaField;
    private Label hexField;
    private Label base2Field;
    private Label base10Field;
    private float value;

    private final String titleString = "EXPOSED FLOAT";
    private final String binaryString = "binary";
    private final String signString = "sign";
    private final String exponentString = "exponent";
    private final String mantissaString = "mantissa";
    private final String hexString = "hex";
    private final String base10String = "radix 10";
    private final String base2String = "radix 2";

    private final String incrementButtonString = "++";
    private final String decrementButtonString = "--";
    private final String multByZeroButtonString = "*=(0)";
    private final String piButtonString = "Pi";
    private final String positiveInfinityButtonString = "+Inf";
    private final String negativeInfinityButtonString = "-Inf";
    private final String maximumButtonString = "Max";
    private final String minimumButtonString = "Min";
    private final String notANumberButtonString = "NaN";
    private final String changeSignButtonString = "*=(-1)";
    private final String doubleButtonString = "*=(2)";
    private final String halveButtonString = "/=(2)";
    private final String notANumberString = "Not A Number";
    private final String positiveInfinityString = "+Infinity";
    private final String negativeInfinityString = "-Infinity";

    Button maximumButton = new Button(maximumButtonString);
    Button minimumButton = new Button(minimumButtonString);
    Button positiveInfinityButton = new Button(positiveInfinityButtonString);
    Button negativeInfinityButton = new Button(negativeInfinityButtonString);
    Button piButton = new Button(piButtonString);
    Button notANumberButton = new Button(notANumberButtonString);

    public void init() {

        Panel buttonPanel = new PanelWithInsets(0, 0, 0, 0);
        buttonPanel.setLayout(new GridLayout(6, 2, 5, 5));
        buttonPanel.add(maximumButton);
        buttonPanel.add(minimumButton);
        buttonPanel.add(positiveInfinityButton);
        buttonPanel.add(negativeInfinityButton);
        buttonPanel.add(piButton);
        buttonPanel.add(notANumberButton);
        buttonPanel.add(new Button(multByZeroButtonString));
        buttonPanel.add(new Button(changeSignButtonString));
        buttonPanel.add(new Button(doubleButtonString));
        buttonPanel.add(new Button(halveButtonString));
        buttonPanel.add(new RepeaterButton(incrementButtonString));
        buttonPanel.add(new RepeaterButton(decrementButtonString));

        binaryField = new Label("00000000000000000000000000000000");
        signField = new Label("0");
        exponentField = new Label("00000000");
        mantissaField = new Label("000000000000000000000000");
        hexField = new Label("00000000");
        base2Field = new Label("0");
        base10Field = new Label("0");

        Font fieldFont = new Font("TimesRoman", Font.PLAIN, 12);
        binaryField.setFont(fieldFont);
        signField.setFont(fieldFont);
        exponentField.setFont(fieldFont);
        mantissaField.setFont(fieldFont);
        hexField.setFont(fieldFont);
        base2Field.setFont(fieldFont);
        base10Field.setFont(fieldFont);

        Panel numberPanel = new Panel();
        numberPanel.setBackground(Color.white);
        numberPanel.setLayout(new GridLayout(7, 1));
        numberPanel.add(signField);
        numberPanel.add(exponentField);
        numberPanel.add(mantissaField);
        Panel binaryPanel = new Panel();
        binaryPanel.setLayout(new BorderLayout());
        binaryPanel.add("Center", binaryField);
        numberPanel.add(binaryPanel);

        Panel hexPanel = new Panel();
        hexPanel.setLayout(new BorderLayout());
        hexPanel.add("Center", hexField);
        numberPanel.add(hexPanel);
        numberPanel.add(base2Field);
        numberPanel.add(base10Field);

        Panel labelPanel = new Panel();
        labelPanel.setBackground(Color.white);
        labelPanel.setLayout(new GridLayout(7, 1));
        Font labelFont = new Font("Helvetica", Font.ITALIC, 11);
        Label label = new Label(signString, Label.CENTER);
        label.setFont(labelFont);
        labelPanel.add(label);
        label = new Label(exponentString, Label.CENTER);
        label.setFont(labelFont);
        labelPanel.add(label);
        label = new Label(mantissaString, Label.CENTER);
        label.setFont(labelFont);
        labelPanel.add(label);
        label = new Label(binaryString, Label.CENTER);
        label.setFont(labelFont);
        labelPanel.add(label);
        label = new Label(hexString, Label.CENTER);
        label.setFont(labelFont);
        labelPanel.add(label);
        label = new Label(base2String, Label.CENTER);
        label.setFont(labelFont);
        labelPanel.add(label);
        label = new Label(base10String, Label.CENTER);
        label.setFont(labelFont);
        labelPanel.add(label);

        Panel dataPanel = new Panel();
        dataPanel.setLayout(new BorderLayout());
        dataPanel.add("West", labelPanel);
        dataPanel.add("Center", numberPanel);

        ColoredLabel title = new ColoredLabel(titleString, Label.CENTER, Color.cyan);
        title.setFont(new Font("Helvetica", Font.BOLD, 12));

        setBackground(Color.green);
        setLayout(new BorderLayout(5, 5));
        add("North", title);
        add("West", buttonPanel);
        add("Center", dataPanel);
    }

    public boolean action(Event evt, Object arg) {

        if (evt.target instanceof Button) {
            String bname = (String) arg;
            if (bname.equals(incrementButtonString)) {

                ++value;
            } else if (bname.equals(decrementButtonString)) {

                --value;
            } else if (bname.equals(multByZeroButtonString)) {

                value *= (float) 0.0;
            } else if (bname.equals(piButtonString)) {

                value = (float) Math.PI;
            } else if (bname.equals(positiveInfinityButtonString)) {

                value = Float.POSITIVE_INFINITY;
            } else if (bname.equals(negativeInfinityButtonString)) {

                value = Float.NEGATIVE_INFINITY;
            } else if (bname.equals(maximumButtonString)) {

                value = Float.MAX_VALUE;
            } else if (bname.equals(minimumButtonString)) {

                value = Float.MIN_VALUE;
            } else if (bname.equals(notANumberButtonString)) {

                value = Float.NaN;
            } else if (bname.equals(changeSignButtonString)) {

                value *= -1.0;
            } else if (bname.equals(doubleButtonString)) {

                value *= 2.0;
            } else if (bname.equals(halveButtonString)) {

                value /= 2.0;
            }
            updateNumberFields();
            enableDisableButton(maximumButton, Float.MAX_VALUE);
            enableDisableButton(minimumButton, Float.MIN_VALUE);
            enableDisableButton(positiveInfinityButton, Float.POSITIVE_INFINITY);
            enableDisableButton(negativeInfinityButton, Float.NEGATIVE_INFINITY);
            enableDisableButton(piButton, (float) Math.PI);
            enableDisableButton(notANumberButton, Float.NaN);
            if (!notANumberButton.isEnabled()) {
                if (!Float.isNaN(value)) {
                    notANumberButton.enable();
                }
            } else if (Float.isNaN(value)) {
                notANumberButton.disable();
            }
        }
        return true;
    }

    void enableDisableButton(Button b, float val) {

        if (!b.isEnabled()) {
            if (value != val) {
                b.enable();
            }
        } else if (value == val) {
            b.disable();
        }
    }

    void updateNumberFields() {

        int intBits = Float.floatToIntBits(value);

        if (Float.isNaN(value)) {
            base10Field.setText(notANumberString);
        } else if (Float.isInfinite(value)) {
            if ((intBits >>> 31) == 1) {
                // This is a negative infinity
                base10Field.setText(negativeInfinityString);
            } else {
                // This is a positive infinity
                base10Field.setText(positiveInfinityString);
            }
        } else if (intBits == (int) 0x80000000) {
            base10Field.setText("-0");
        } else {
            base10Field.setText(Float.toString(value));
        }

        int v = intBits;
        StringBuffer buf = new StringBuffer();
        for (int i = 0; i < 8; ++i) {
            // Get lowest bit
            int remainder = v & 0xf;

            // Convert bit to a character and insert it into the beginning of the string
            switch (remainder) {
            case 0:
                buf.insert(0, "0");
                break;
            case 1:
                buf.insert(0, "1");
                break;
            case 2:
                buf.insert(0, "2");
                break;
            case 3:
                buf.insert(0, "3");
                break;
            case 4:
                buf.insert(0, "4");
                break;
            case 5:
                buf.insert(0, "5");
                break;
            case 6:
                buf.insert(0, "6");
                break;
            case 7:
                buf.insert(0, "7");
                break;
            case 8:
                buf.insert(0, "8");
                break;
            case 9:
                buf.insert(0, "9");
                break;
            case 10:
                buf.insert(0, "a");
                break;
            case 11:
                buf.insert(0, "b");
                break;
            case 12:
                buf.insert(0, "c");
                break;
            case 13:
                buf.insert(0, "d");
                break;
            case 14:
                buf.insert(0, "e");
                break;
            case 15:
                buf.insert(0, "f");
                break;
            }

            // Shift the int to the right one bit
            v >>>= 4;
        }
        hexField.setText(buf.toString());

        v = intBits;
        buf.setLength(0);
        for (int i = 0; i < 32; ++i) {
            // Get lowest bit
            int remainder = v & 0x1;

            // Convert bit to a character and insert it into the beginning of the string
            if (remainder == 0) {
                buf.insert(0, "0");
            } else {
                buf.insert(0, "1");
            }

            // Shift the int to the right one bit
            v >>>= 1;
        }
        binaryField.setText(buf.toString());

        if (intBits < 0) {

            signField.setText("1");
        } else {

            signField.setText("0");
        }

        v = intBits >> 23;
        buf.setLength(0);
        for (int i = 0; i < 8; ++i) {
            // Get lowest bit
            int remainder = v & 0x1;

            // Convert bit to a character and insert it into the beginning of the string
            if (remainder == 0) {
                buf.insert(0, "0");
            } else {
                buf.insert(0, "1");
            }

            // Shift the int to the right one bit
            v >>>= 1;
        }
        exponentField.setText(buf.toString());

        // Do the mantissa
        v = intBits;
        buf.setLength(0);
        for (int i = 0; i < 23; ++i) {
            // Get lowest bit
            int remainder = v & 0x1;

            // Convert bit to a character and insert it into the beginning of the string
            if (remainder == 0) {
                buf.insert(0, "0");
            } else {
                buf.insert(0, "1");
            }

            // Shift the int to the right one bit
            v >>>= 1;
        }
        if (((intBits >> 23) & 0xff) == 0) {
            // This is a denormalized number, first bit is 0
            buf.insert(0, "0");
        } else {
            // This is a normalized number, first bit is 1
            buf.insert(0, "1");
        }
        mantissaField.setText(buf.toString());

        // Print out a denormalized base 2 version.
        buf.setLength(0);
        if (Float.isNaN(value)) {
            buf.append(notANumberString);
        } else if (Float.isInfinite(value)) {
            if ((intBits >>> 31) == 1) {
                // This is a negative infinity
                buf.append(negativeInfinityString);
            } else {
                // This is a positive infinity
                buf.append(positiveInfinityString);
            }
        } else {

            if ((intBits >>> 31) == 1) {
                // This is a negative number
                buf.append("-");
            }

            // Convert mantissa to int.
            v = (intBits & 0x007fffff);
            if (((intBits >> 23) & 0xff) != 0) {
                // Set bit 23 if the number is normalized
                v |= 0x00800000;
            }
            buf.append(v);

            // print out the exponent
            v = (intBits >> 23) & 0xff;
            if (v != 150 && intBits != 0 && intBits != (int) 0x80000000) {
                if (v != 0) {
                    // regular normalized number
                    buf.append("e" + (v - 150));
                } else {
                    // denormalized number
                    buf.append("e-149");
                }
            }
        }

        base2Field.setText(buf.toString());
    }

    public Insets insets() {
        return new Insets(5, 5, 5, 5);
    }
}

// I used this class because I can't seem to set the background color of
// a label.  I only want a label, but I want the backgound to be gray.
class ColoredLabel extends Panel {

    private Label theLabel;

    ColoredLabel(String label, int alignment, Color color) {

        setLayout(new GridLayout(1, 1));

        setBackground(color);

        theLabel = new Label(label, alignment);

        add(theLabel);
    }

    public void setLabelText(String s) {

        theLabel.setText(s);
    }

    public Insets insets() {
        return new Insets(0, 0, 0, 0);
    }
}

class GrayButton extends Button {

    GrayButton(String label) {

        super(label);
        setBackground(Color.lightGray);
    }
}

class PanelWithInsets extends Panel {

    private int top;
    private int left;
    private int bottom;
    private int right;

    PanelWithInsets(int t, int l, int b, int r) {
        top = t;
        left = l;
        bottom = b;
        right = r;
    }

    PanelWithInsets() {
        top = 5;
        left = 5;
        bottom = 5;
        right = 5;
    }

    public Insets insets() {
        return new Insets(top, left, bottom, right);
    }
}

class RepeaterButton extends GrayButton {

    RepeaterButton(String label) {

        super(label);
    }
}