PrintWriter пишет совершенно неразборчиво, когда задает заданные значения c - PullRequest
0 голосов
/ 18 февраля 2020

Ради интереса я решил написать программу, которая будет рассчитывать ваш средний балл для всех возможных комбинаций оценок с учетом списка кредитных часов. Код:

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.math.RoundingMode;
import java.nio.charset.StandardCharsets;
import java.text.DecimalFormat;

public class GPA_Math_Testing {
    public static void main(String[] args) throws IOException {
        PrintWriter file = new PrintWriter("out.txt", StandardCharsets.UTF_8);
        //starting points & hours
        double initPoints = 131.60;
        int initHours = 40;
        //list of hours this semester
        int[] hours = new int[]{3, 3, 3, 4, 4};
        //minimum gpa to print to "filtered.txt"
        double gpaMin = 3.25;

        //array to store grade combinations
        double[][] grades = new double[(int) Math.pow(13, hours.length)][hours.length];

        //generating all possible combinations of grades
        for (int i = 0; i < hours.length; i++) {
            double grade = 0;
            int count = 0;
            for (int j = 0; j < Math.pow(13, hours.length); j++) {
                grades[j][i] = grade;
                count++;
                if (count == (int) Math.pow(13, i)) {
                    grade = onePlace(incGrade(grade));
                    count = 0;
                }
            }
        }

        //array to store cumulative gpa
        double[] totalGrades = new double[(int) Math.pow(13, hours.length)];
        //calculate cumulative gpa for each combination
        for (int i = 0; i < (int) Math.pow(13, hours.length); i++) {
            double sum = 0;
            for (int j = 0; j < hours.length; j++) {
                //only time hours[i] is ever accessed
                sum += grades[i][j] * hours[j];
            }
            totalGrades[i] = twoPlace((sum + initPoints) / (initHours + sumArr(hours)));
        }

        //print full list to "out.txt"
        printArr(grades, totalGrades, file);
        file.close();

        //print combinations that reach the minimum to "filtered.txt"
        PrintWriter filtered = new PrintWriter("filtered.txt", StandardCharsets.UTF_8);
        try (BufferedReader br = new BufferedReader(new FileReader("out.txt"))) {
            String line;
            while ((line = br.readLine()) != null) {
                if (Double.parseDouble(line.substring(line.indexOf('|') + 2)) >= gpaMin) {
                    filtered.println(line);
                }
            }
        }
        filtered.close();
    }


    //function to increase grade one step; wraps back from 4.0 to 0.0
    public static double incGrade(double grade) {
        if (onePlace(grade % 1.0) == 0.0) {
            grade = onePlace(grade + 0.3);
        } else if (onePlace(grade % 1.0) == 0.3) {
            grade = onePlace(grade + 0.4);
        } else if (onePlace(grade % 1.0) == 0.7) {
            grade = onePlace(grade + 0.3);
        }
        if (onePlace(grade) >= 4.1) {
            grade = 0.0;
        }
        return grade;
    }

    //rounding functions
    public static double onePlace(double i) {
        DecimalFormat onePlace = new DecimalFormat("#.#");
        return Double.parseDouble(onePlace.format(i));
    }

    public static double twoPlace(double i) {
        DecimalFormat twoPlace = new DecimalFormat("#.##");
        twoPlace.setRoundingMode(RoundingMode.FLOOR);
        return Double.parseDouble(twoPlace.format(i));
    }

    //find sum of array values
    public static int sumArr(int[] a) {
        int sum = 0;
        for (int i : a) {
            sum += i;
        }
        return sum;
    }

    //functions to print arrays
    public static void printArr(double[][] a, double[] g) {
        for (int j = 0; j < g.length; j++) {
            for (int i = 0; i < a[j].length; i++) {
                System.out.print(a[j][i] + " ");
            }
            System.out.print(" | " + g[j] + '\n');
        }
    }

    public static void printArr(double[][] a, double[] g, PrintWriter file) {
        for (int i = 0; i < a.length; i++) {
            for (int j = 0; j < a[i].length; j++) {
                file.print(a[i][j] + " ");
            }
            file.print(" | " + g[i] + '\n');
        }

    }
}

Как и сейчас, код работает отлично. Однако, если я изменю hours[] на {3, 3, 3, 4} или {3, 3, 4, 3}, то out.txt просто будет заполнен десятками тысяч бессмысленных символов.

Образец мусорного текста:

‰⸰‰⸰‰簠㈠㜮ਸ਼⸳″⸲‰⸰‰⸰‰簠㈠㜮ਸ⸳‷⸲‰⸰‰⸰‰簠㈠㠮㐊〮㈠〮〠〮〠〮†⁼⸲㈸《〮㈠㌮〠〮〠〮†⁼⸲ㄶ《㌮㈠㌮〠〮〠〮†⁼⸲㌶《㜮㈠㌮〠

Это происходит только тогда, когда initPoints = 131.60, initHours = 40 и hours[] равны {3, 3, 3, 4} или {3, 3, 4, 3}. До сих пор я не смог повторить это с любой другой комбинацией значений. Изменение sum += grades[i][j] * hours[j]; на sum += grades[i][j] * 1; решает проблему, но я абсолютно не представляю, почему умножение на hours[j] может вызвать это, и только с невероятно заданными c комбинациями значений. Печать на консоль вместо out.txt дает отлично читаемый текст, и самое странное для меня то, что filtered.txt также отлично читается, даже если out.txt нет.

РЕДАКТИРОВАТЬ: решил попробовать вместо этого открываем нечитаемый out.txt с помощью notepad ++, и он отображается нормально. Он также работает в Wordpad, только в Windows Notepad он отображается странно.

...