Untitled

 avatar
unknown
plain_text
10 months ago
12 kB
24
Indexable
/*
 * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
 */

package com.cc11c.radixconverter;

/**
 *
 * @author M304User
 */
import java.util.Scanner;
import java.util.ArrayList;

public class RadixConverter {
    private static final String DIGITS = "0123456789ABCDEF";
    private static final int FRACTION_PRECISION = 10;

    // ========================= MAIN =========================
    public static void main(String[] args) {
        ArrayList<String[]> results = new ArrayList<>(); // store results as String arrays now
        try (Scanner scanner = new Scanner(System.in)) {

            int[] allowedBases = {2, 8, 10, 16};

            while (true) {
                System.out.print("Enter origin base (2, 8, 10, 16): ");
                String baseInput = scanner.nextLine().trim();
                if (baseInput.equals("STOP")) break;

                int originBase;
                try {
                    originBase = Integer.parseInt(baseInput);

                    boolean isValidBase = false;
                    for (int base : allowedBases) {
                        if (originBase == base) {
                            isValidBase = true;
                            break;
                        }
                    }

                    if (!isValidBase) {
                        System.out.println(">> Invalid base. Only bases 2, 8, 10, and 16 are allowed.\n");
                        continue;
                    }
                } catch (NumberFormatException e) {
                    System.out.println(">> Invalid input. Enter 2, 8, 10, or 16.\n");
                    continue;
                }

                System.out.print("Enter number in base " + originBase + ": ");
                String numberInput = scanner.nextLine().trim();
                if (numberInput.equals("STOP")) break;

                double decimalValue;
                try {
                    if (originBase == 10 || !numberInput.matches("[0-9A-Fa-f]+(\\.[0-9A-Fa-f]+)?")) {
                        decimalValue = evaluateExpression(numberInput);
                    } else {
                        decimalValue = toDecimal(numberInput, originBase);
                    }
                } catch (Exception e) {
                    System.out.println(">> Invalid input: " + e.getMessage() + "\n");
                    continue;
                }
                
                System.out.println("");

                String output1 = "", output2 = "", output3 = "";
                switch (originBase) {
                    case 2 -> {
                        output1 = formatOutput(decimalValue, 8, FRACTION_PRECISION);
                        output2 = formatOutput(decimalValue, 10, FRACTION_PRECISION);
                        output3 = formatOutput(decimalValue, 16, FRACTION_PRECISION);
                    }
                    case 8 -> {
                        output1 = formatOutput(decimalValue, 2, FRACTION_PRECISION);
                        output2 = formatOutput(decimalValue, 10, FRACTION_PRECISION);
                        output3 = formatOutput(decimalValue, 16, FRACTION_PRECISION);
                    }
                    case 10 -> {
                        output1 = formatOutput(decimalValue, 2, FRACTION_PRECISION);
                        output2 = formatOutput(decimalValue, 8, FRACTION_PRECISION);
                        output3 = formatOutput(decimalValue, 16, FRACTION_PRECISION);
                    }
                    case 16 -> {
                        output1 = formatOutput(decimalValue, 2, FRACTION_PRECISION);
                        output2 = formatOutput(decimalValue, 8, FRACTION_PRECISION);
                        output3 = formatOutput(decimalValue, 10, FRACTION_PRECISION);
                    }
                }

                // Store as an array for easier dynamic formatting
                results.add(new String[]{
                    formatOutput(decimalValue, originBase, FRACTION_PRECISION),
                        output1,
                        output2,
                        output3
                    });
            }

            // Display results only when the user enters "STOP"
            if (!results.isEmpty()) {
                // Calculate max width per column dynamically
                int inputWidth = "Input".length();
                int out1Width = "Output 1".length();
                int out2Width = "Output 2".length();
                int out3Width = "Output 3".length();

                for (String[] row : results) {
                    if (row[0].length() > inputWidth) inputWidth = row[0].length();
                    if (row[1].length() > out1Width) out1Width = row[1].length();
                    if (row[2].length() > out2Width) out2Width = row[2].length();
                    if (row[3].length() > out3Width) out3Width = row[3].length();
                }

                // Add some padding for readability
                inputWidth += 2;
                out1Width += 2;
                out2Width += 2;
                out3Width += 2;

                String formatString = String.format("%%-%ds %%-%ds %%-%ds %%-%ds", inputWidth, out1Width, out2Width, out3Width);

                // Print header
                System.out.println(String.format(formatString, "Input", "Output 1", "Output 2", "Output 3"));

                // Print all results
                for (String[] row : results) {
                    System.out.println(String.format(formatString, row[0], row[1], row[2], row[3]));
                }
                System.out.println();
            }
        }
    }

    // ========================= DECIMAL → RADIX =========================
    public static String fromDecimal(double decimal, int base, int precision) {
        if (decimal == 0) return "0";
        boolean negative = decimal < 0;
        decimal = Math.abs(decimal);

        long wholePart = (long) decimal;
        double fracPart = decimal - wholePart;

        StringBuilder sb = new StringBuilder();

        if (wholePart == 0) sb.append('0');
        else {
            StringBuilder wholeStr = new StringBuilder();
            while (wholePart > 0) {
                wholeStr.append(DIGITS.charAt((int) (wholePart % base)));
                wholePart /= base;
            }
            sb.append(wholeStr.reverse());
        }

        if (fracPart > 0) {
            sb.append('.');
            int count = 0;
            while (fracPart > 0 && count < precision) {
                fracPart *= base;
                int digit = (int) fracPart;
                sb.append(DIGITS.charAt(digit));
                fracPart -= digit;
                count++;
            }
        }

        return negative ? "-" + sb.toString() : sb.toString();
    }

    public static double toDecimal(String number, int base) {
        number = number.toUpperCase();
        String[] parts = number.split("\\.");
        double result = 0;

        for (char c : parts[0].toCharArray()) {
            int digit = DIGITS.indexOf(c);
            if (digit == -1 || digit >= base) throw new NumberFormatException("Invalid digit '" + c + "' for base " + base);
            result = result * base + digit;
        }

        if (parts.length > 1) {
            double frac = 0;
            double power = base;
            for (char c : parts[1].toCharArray()) {
                int digit = DIGITS.indexOf(c);
                if (digit == -1 || digit >= base) throw new NumberFormatException("Invalid digit '" + c + "' for base " + base);
                frac += digit / power;
                power *= base;
            }
            result += frac;
        }

        return result;
    }

    public static String toSubscript(int base) {
        String baseStr = String.valueOf(base);
        StringBuilder subscript = new StringBuilder();
        for (char c : baseStr.toCharArray()) {
            switch (c) {
                case '0' -> subscript.append('₀');
                case '1' -> subscript.append('₁');
                case '2' -> subscript.append('₂');
                case '3' -> subscript.append('₃');
                case '4' -> subscript.append('₄');
                case '5' -> subscript.append('₅');
                case '6' -> subscript.append('₆');
                case '7' -> subscript.append('₇');
                case '8' -> subscript.append('₈');
                case '9' -> subscript.append('₉');
            }
        }
        return subscript.toString();
    }

    public static String formatOutput(double decimalValue, int base, int precision) {
        return "(" + fromDecimal(decimalValue, base, precision).toUpperCase() + ")" + toSubscript(base);
    }

    // ========================= EXPRESSION EVALUATION =========================
    public static double evaluateExpression(String expr) {
        return new Object() {
            int pos = -1, ch;

            void nextChar() { ch = (++pos < expr.length()) ? expr.charAt(pos) : -1; }

            boolean eat(int charToEat) {
                while (ch == ' ') nextChar();
                if (ch == charToEat) { nextChar(); return true; }
                return false;
            }

            double parse() {
                nextChar();
                double x = parseExpression();
                if (pos < expr.length()) throw new RuntimeException("Unexpected: " + (char)ch);
                return x;
            }

            double parseExpression() {
                double x = parseTerm();
                while (true) {
                    if      (eat('+')) x += parseTerm();
                    else if (eat('-')) x -= parseTerm();
                    else return x;
                }
            }

            double parseTerm() {
                double x = parseFactor();
                while (true) {
                    if      (eat('*')) x *= parseFactor();
                    else if (eat('/')) x /= parseFactor();
                    else return x;
                }
            }

            double parseFactor() {
                if (eat('+')) return parseFactor();
                if (eat('-')) return -parseFactor();

                double x;
                int startPos = this.pos;

                if (eat('(')) { x = parseExpression(); eat(')'); }
                else if ((ch >= '0' && ch <= '9') || ch == '.') {
                    while ((ch >= '0' && ch <= '9') || ch == '.' || ch == 'e' || ch == 'E') {
                        if (ch == 'e' || ch == 'E') { nextChar(); if (ch == '+' || ch == '-') nextChar(); }
                        else nextChar();
                    }
                    x = Double.parseDouble(expr.substring(startPos, this.pos));
                }
                else if (Character.isLetter(ch) || ch == 'π') {
                    while (Character.isLetter(ch) || ch == 'π') nextChar();
                    String func = expr.substring(startPos, this.pos);
                    switch (func.toLowerCase()) {
                        case "pi", "π" -> x = Math.PI;
                        case "e" -> x = Math.E;
                        case "sqrt" -> x = Math.sqrt(parseFactor());
                        case "sin"  -> x = Math.sin(parseFactor());
                        case "cos"  -> x = Math.cos(parseFactor());
                        case "tan"  -> x = Math.tan(parseFactor());
                        case "log"  -> x = Math.log10(parseFactor());
                        case "ln"   -> x = Math.log(parseFactor());
                        case "abs"  -> x = Math.abs(parseFactor());
                        default -> throw new RuntimeException("Unknown function: " + func);
                    }
                } else throw new RuntimeException("Unexpected: " + (char)ch);

                if (eat('^')) x = Math.pow(x, parseFactor());

                if (eat('!')) {
                    if (x < 0) throw new IllegalArgumentException("Factorial of negative number not defined.");
                    long f = 1;
                    for (int i = 2; i <= (int)x; i++) f *= i;
                    x = f;
                }

                return x;
            }
        }.parse();
    }
}
Editor is loading...
Leave a Comment