1

I am coding a java-based calculator and just wanted to show any value over 100,000 into scientific notation format. I'm wondering how you would display the number, change it back into long form for calculations on the back-end, and then display it once again in clean, scientific notation. I would like it to be as simple as possible as I am not a master by any means at java, I have just started learning it about two months ago.

package javacalc;

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.swing.*;
import java.text.DecimalFormat;

public class CalcGUI extends JFrame implements ActionListener { 
    final static String PROJ_TITLE = "Calculator";
    final static String PROJ_AUTHORS = String.format("Jaren Browne%nKevin Miller");

    final static int[] PROJ_WINDOW_SIZE = {490, 650};
    final static int[] PROJ_WINDOW_LOCATION = {300, 300};

    GridBagConstraints gbcCalcPanel = new GridBagConstraints();
    GridBagConstraints gbcButtonPanel = new GridBagConstraints();
    JPanel calcPanel = new JPanel();
    JTextField upperDisplay;
    JTextField lowerDisplay;
    
    private static char operation;
    private static double firstNumber = 0;
    private static double secondNumber = 0;
    private static double mem = 0;
    private static boolean clearScreen = true;
    
    DecimalFormat df = new DecimalFormat("0.##############");
    
    @Override
    public void actionPerformed(ActionEvent e) {
        String command = e.getActionCommand();
        String displayString = upperDisplay.getText();
        
        if (digitTest(command)) {
            updateDisplay(command);
            return;
        }

        // Basic arithmetic
        if (command.equals("=") || command.equals("+") || command.equals("-") || command.equals("x") || command.equals("÷") || command.equals("%")) {
            clearScreen = true;

            try {
                if (!calculate(Double.parseDouble(displayString))) {
                    updateDisplay("DIV / 0");
                    reset();
                    return;
                }
            } catch (NumberFormatException ex) {}

            updateDisplay("" + df.format(secondNumber));
            clearScreen = true;
            operation = command.charAt(0);
            firstNumber = secondNumber;
            return;
        }

        switch (command) {
            case ".":                   // decimal
                updateDisplay(".");
                break;

            // Pos/Neg pressed
            case "+/-":
                clearScreen = true;
                if (!upperDisplay.getText().equals("0")) {
                    try {
                        double inverse = Double.parseDouble(displayString);
                        inverse *= -1;
                        updateDisplay(df.format(inverse));
                    } catch (NumberFormatException ex) {
                        updateDisplay("0");
                    }
                }
                break;
                
            // Clear pressed
            case "CE":
                reset();
                updateDisplay("0");
                break;

            // Backspace pressed
            case "<-":
                if (clearScreen) {
                    updateDisplay("0");
                } else {
                    deletePressed();
                }
                break;
                
            case "MC":
                mem = 0;
                break;
                
            case "MR":
                clearScreen = true;
                updateDisplay("" + df.format(mem));
                clearScreen = true;
                break;
                
            case "M+":
                try {
                    mem += Double.parseDouble(displayString);
                } catch (NumberFormatException ex) {}
                break;
                
            case "M-":
                try {
                    mem -= Double.parseDouble(displayString);
                } catch (NumberFormatException ex) {}
                break;
                
            case "π":
                clearScreen = true;
                updateDisplay(String.valueOf(Math.PI));
                clearScreen = true;
                break;
                
            case "xⁿ":
                clearScreen = true;
                calculate(Double.parseDouble(displayString));
                updateDisplay("" + df.format(secondNumber));
                operation = '^';
                firstNumber = secondNumber;
                clearScreen = true;
                break;
            
            case "√":
                clearScreen = true;
                calculate(Double.parseDouble(displayString));
                updateDisplay("" + df.format(secondNumber));
                operation = '√';
                firstNumber = secondNumber;
                clearScreen = true;
                break;

            case "ⁿ√":
                clearScreen = true;
                calculate(Double.parseDouble(displayString));
                updateDisplay("" + df.format(secondNumber));
                operation = '&';
                firstNumber = secondNumber;
                clearScreen = true;
                break;
                
            case "sin":
                clearScreen = true;
                calculate(Double.parseDouble(displayString));
                updateDisplay("" + df.format(secondNumber));
                operation = 'S';
                firstNumber = secondNumber;
                clearScreen = true;
                break;

            case "cos":
                clearScreen = true;
                calculate(Double.parseDouble(displayString));
                updateDisplay("" + df.format(secondNumber));
                operation = 'C';
                firstNumber = secondNumber;
                clearScreen = true;
                break;

            case "tan":
                clearScreen = true;
                calculate(Double.parseDouble(displayString));
                updateDisplay("" + df.format(secondNumber));
                operation = 'T';
                firstNumber = secondNumber;
                clearScreen = true;
                break;
                
            case "sin‾¹":
                clearScreen = true;
                calculate(Double.parseDouble(displayString));
                updateDisplay("" + df.format(secondNumber));
                operation = 's';
                firstNumber = secondNumber;
                clearScreen = true;
                break;
                
            case "cos‾¹":
                clearScreen = true;
                calculate(Double.parseDouble(displayString));
                updateDisplay("" + df.format(secondNumber));
                operation = 'c';
                firstNumber = secondNumber;
                clearScreen = true;
                break;

            case "tan‾¹":
                clearScreen = true;
                calculate(Double.parseDouble(displayString));
                updateDisplay("" + df.format(secondNumber));
                operation = 't';
                firstNumber = secondNumber;
                clearScreen = true;
                break;

        }
    }
   
    private boolean calculate(double displayNumber) {
        secondNumber = displayNumber;
        
        switch (operation) {
            case '+':           // Addition
                secondNumber += firstNumber;
                break;

            case '-':           // Subtraction
                secondNumber = firstNumber - secondNumber;
                break;

            case 'x':           // Multiplication
                secondNumber *= firstNumber;
                break;

            case '÷':           // Division
                try {
                    int divZeroTest = (int) firstNumber / (int) secondNumber;
                    secondNumber = firstNumber / secondNumber;
                    break;
                } catch (ArithmeticException ex){
                    clearScreen = true;
                    return false;
                }
                
            case '%':           // Percentage
                secondNumber = (firstNumber / 100) * secondNumber;
                break;
                
            case '^':           // Exponential power
                secondNumber = Math.pow(firstNumber, secondNumber);
                break;
                
            case '√':           // Square root
                if (firstNumber == 0) {
                    firstNumber = 1;
                }
                secondNumber = firstNumber * Math.sqrt(secondNumber);
                break;
                
            case '&':           // Exponential root
                secondNumber = Math.pow(secondNumber, (1 / firstNumber));
                break;
                
            case 'S':
                if (firstNumber == 0) {
                    firstNumber = 1;
                }
                secondNumber = firstNumber * Math.sin(Math.toRadians(secondNumber));
                break;
                
            case 'C':
                if (firstNumber == 0) {
                    firstNumber = 1;
                }
                secondNumber = firstNumber * Math.cos(Math.toRadians(secondNumber));
                break;

            case 'T':
                if (firstNumber == 0) {
                    firstNumber = 1;
                }
                secondNumber = firstNumber * Math.tan(Math.toRadians(secondNumber));
                break;
                
            case 's':
                if (firstNumber == 0) {
                    firstNumber = 1;
                }
                secondNumber = firstNumber * Math.toDegrees(Math.asin(secondNumber));
                break;

            case 'c':
                if (firstNumber == 0) {
                    firstNumber = 1;
                }
                secondNumber = firstNumber * Math.toDegrees(Math.acos(secondNumber));
                break;

            case 't':
                if (firstNumber == 0) {
                    firstNumber = 1;
                }
                secondNumber = firstNumber * Math.toDegrees(Math.atan(secondNumber));
                break;

        }
        return true;
    }
    
    // MAIN CONSTRUCT
    public CalcGUI() {
        initGUI();

        calcPanel.setLayout(new GridBagLayout());
        
        // Add display box
        gbcCalcPanel.gridx = 0;
        gbcCalcPanel.gridy = 0;
        gbcCalcPanel.fill = GridBagConstraints.HORIZONTAL;
        gbcCalcPanel.gridwidth = 1;
        calcPanel.add(upperDisplay = buildDisplay(), gbcCalcPanel);
        
//        // Add second display box
//        gbcCalcPanel.gridx = 0;
//        gbcCalcPanel.gridy = 1;
//        gbcCalcPanel.fill = GridBagConstraints.HORIZONTAL;
//        gbcCalcPanel.gridwidth = 1;
//        calcPanel.add(lowerDisplay = buildDisplay(), gbcCalcPanel);
                
        // Add advanced calculator buttons
        gbcCalcPanel.gridx = 0;
        gbcCalcPanel.gridy = 2;
        gbcCalcPanel.weighty = 1;
        gbcCalcPanel.fill = GridBagConstraints.BOTH;
        calcPanel.add(buildAdvancedButtonPanel(), gbcCalcPanel);
        
        // Add calculator buttons
        gbcCalcPanel.gridx = 0;
        gbcCalcPanel.gridy = 3;
        gbcCalcPanel.weighty = 1;
        gbcCalcPanel.fill = GridBagConstraints.BOTH;        
        calcPanel.add(buildButtonPanel(), gbcCalcPanel);
        
        setContentPane(calcPanel);
        pack();
    }

    // DISPLAY BOX
    private JTextField buildDisplay() {
        JTextField t = new JTextField("", 16);
        t.setHorizontalAlignment(SwingConstants.RIGHT);
        t.setBackground(Color.DARK_GRAY);
        t.setForeground(Color.GREEN);
        t.setText("0");
        t.setCaretPosition(1);

        InputStream fontStream = ClassLoader.getSystemClassLoader().getResourceAsStream("DS-DIGII.TTF");
        try {
            Font calcDisplayFont = Font.createFont(Font.TRUETYPE_FONT, fontStream).deriveFont(60f);
            GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
            ge.registerFont(calcDisplayFont);
            t.setFont(calcDisplayFont);
        } catch (IOException | FontFormatException ex) {
            System.out.println(ex.getMessage());
            Font calcDisplayFont = new Font("Lucida Console", Font.BOLD, 40);
            t.setFont(calcDisplayFont);
        }


        return t;
    }
    
    // MAIN BUTTON PANEL
    private JPanel buildButtonPanel() {
        JPanel panel = new JPanel();
        panel.setLayout(new GridBagLayout());
        panel.setBackground(Color.gray);
        
        String[][] buttonText = {{"MC", "MR", "M-", "M+", "÷"},
                                {"+/-", "7", "8", "9", "x"},
                                {"%", "4", "5", "6", "-"},
                                {"√", "1", "2", "3", "+"},
                                {"CE", "0", ".", "=", "+"}};

        int maxWidth = buttonText[0].length;
        int maxHeight = buttonText.length;
        JButton[][] calcButton = new JButton[maxHeight][maxWidth];
        
        // cycle through button array and build
        for (int yPos = 0; yPos < maxHeight; yPos++) {
            for (int xPos = 0; xPos < maxWidth; xPos++) {
                
                // build button panel, skipping button for extended '+' button
                if (!(yPos == 4 && xPos == 4)) {
                    calcButton[yPos][xPos] = new JButton(buttonText[yPos][xPos]);
                    calcButton[yPos][xPos].setFont(calcButton[yPos][xPos].getFont().deriveFont(30f));
                    calcButton[yPos][xPos].setBackground(Color.black);
                    calcButton[yPos][xPos].addActionListener(this);

                    gbcButtonPanel.gridx = xPos;
                    gbcButtonPanel.gridy = yPos;
                    gbcButtonPanel.gridwidth = 1;
                    gbcButtonPanel.weightx = 1;
                    gbcButtonPanel.weighty = 1;
                    Insets buttonSpacing = new Insets(2,2,2,2);
                    gbcButtonPanel.insets = buttonSpacing;
                    
                    // if the button being added is '+' extended it vertically
                    if (yPos == 3 && xPos == 4) {
                        gbcButtonPanel.gridheight = 2;
                        gbcButtonPanel.fill = GridBagConstraints.BOTH;
                    } else {
                        gbcButtonPanel.gridheight = 1;
                        gbcButtonPanel.fill = GridBagConstraints.BOTH;
                    }
                    panel.add(calcButton[yPos][xPos], gbcButtonPanel);
                }
            }
        }

        return panel;
    }
    
    // ADDITIONAL BUTTON PANEL
    private JPanel buildAdvancedButtonPanel() {
        JPanel panel = new JPanel();
        panel.setLayout(new GridBagLayout());
        panel.setBackground(Color.darkGray);
        
        String[][] buttonText = {{"<-", "xⁿ", "sin", "cos", "tan"},
                                {"π", "ⁿ√", "sin‾¹", "cos‾¹", "tan‾¹"}};

        int maxWidth = buttonText[0].length;
        int maxHeight = buttonText.length;
        JButton[][] calcButton = new JButton[maxHeight][maxWidth];
        
        // cycle through button array and build
        for (int yPos = 0; yPos < maxHeight; yPos++) {
            for (int xPos = 0; xPos < maxWidth; xPos++) {
                calcButton[yPos][xPos] = new JButton(buttonText[yPos][xPos]);
                calcButton[yPos][xPos].setFont(calcButton[yPos][xPos].getFont().deriveFont(30f));
                calcButton[yPos][xPos].addActionListener(this);
                
                gbcButtonPanel.gridx = xPos;
                gbcButtonPanel.gridy = yPos;
                gbcButtonPanel.gridwidth = 1;
                gbcButtonPanel.weightx = 1;
                gbcButtonPanel.weighty = 1;
                gbcButtonPanel.gridheight = 1;
                Insets buttonSpacing = new Insets(2,2,2,2);
                gbcButtonPanel.insets = buttonSpacing;
                gbcButtonPanel.fill = GridBagConstraints.BOTH;
                
                panel.add(calcButton[yPos][xPos], gbcButtonPanel);
            }
        }
        return panel;
    }
    
    // INITIALIZE GUI LOOK AND FEEL
    private void initGUI() {
        try {
            // sets the look and feel to that of the OS if possible
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (UnsupportedLookAndFeelException | ClassNotFoundException | InstantiationException | IllegalAccessException ex) {
            // tell us a story
            System.out.printf("Unable to load GUI.%n%s%n", ex.getMessage());
        } 
        
        // set some window and frame options
        setTitle(PROJ_TITLE);
        setResizable(false);
        setLocation(PROJ_WINDOW_LOCATION[0], PROJ_WINDOW_LOCATION[1]);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
    
    // TEST IF REQUEST IS A NUMBER
    private boolean digitTest(String s) {
        try {
            Integer.parseInt(s);
            return true;
        } catch (NumberFormatException ex) {
            return false;
        }
    }
    
    // UPDATE DISPLAY
    private void updateDisplay(String displayDigits) {
        String displayString = upperDisplay.getText();

        // Does screen need cleared before moving forward?
        if (clearScreen) {
            displayString = "0";
            upperDisplay.setText(displayString);
            clearScreen = false;
        }   
        
        // Decimal handler
        if (displayDigits.equals(".")){
            if (!displayString.contains(displayDigits)) {
                if (displayString.equals("0")) {
                    displayString = String.format("0%s", displayDigits);
                } else {
                    displayString = String.format("%s", displayString + displayDigits);
                }
            }
        } else {        // No decimal
            if (displayString.equals("0")) {
                displayString = String.format("%s", displayDigits);
            } else {
                displayString = String.format(displayString + displayDigits);
            }
        }
        

        // Check for DIV/0 and format string for display length
        try {            
        // Check length and truncate
            if (Double.parseDouble(displayString) < 0 && displayString.length() > 16) {
                displayString = displayString.substring(0,16);
            } else if (Double.parseDouble(displayString) > 0 && displayString.length() > 15) {
                displayString = displayString.substring(0,15);
            } else if (Double.isNaN(Double.parseDouble(displayString))) {
                displayString = String.format("%-16s", "Domain Error");
                reset();
            }
        } catch (NumberFormatException ex) {
            displayString = String.format("%-17s", displayDigits);
        }
        
        upperDisplay.setText(displayString);
    }

    // DELETE LAST CHARACTER
    private void deletePressed(){
        int l = upperDisplay.getText().length();
        int n = upperDisplay.getText().length() - 1;
        
        if (l > 1) {
            StringBuilder backSpace = new StringBuilder(upperDisplay.getText());
            upperDisplay.setText(backSpace.deleteCharAt(n).toString());
        } else {
            upperDisplay.setText("0");
        }
    }
    
    // CLEAR VARIABLES AND RESET
    private void reset() {
        firstNumber = 0;
        secondNumber = 0;
        operation = ' ';
        clearScreen = true;
    }
    
}
  • I think, for starters, your 100,000 limit doesn't make sense. You probably meant 99,999.99. Second, do you want to create your own method or use a library for the conversion? I assume you want to do your own. – hfontanez Apr 05 '22 at 00:00
  • You should be able to get the `ChoiceFormat` class to do this. If not, you could write your own implementation of `NumberFormat`. – Dawood ibn Kareem Apr 05 '22 at 00:03
  • 1
    For [example](https://stackoverflow.com/questions/2944822/format-double-value-in-scientific-notation) – MadProgrammer Apr 05 '22 at 00:04

1 Answers1

0

Oddly enough, I've normally had the reverse problem ;) Using no format normally sees scientific notation happen automatically, though I haven't looked into the docs to see when it happens. An experiment rather than an answer:

public class WhenScientific {
    public static void main(String[] args) {
        try {
            double d = 1.0;
            for(int i = 0;i < 10;i++) {  
                System.out.println(d);
                d *= 10;
            }
        }
        catch(Throwable t) {
            t.printStackTrace();
        }
    }
}
g00se
  • 3,207
  • 2
  • 5
  • 9