Unit Circle程序舍入问题:单位圆计算结果与预期不符求修复
Let's break down why your current code is giving unexpected results, and how to fix it to match the expected output.
The Root of the Problem
Your main issue is modifying the loop variable i inside the loop with i = Math.round(i * 100) / 100.0;. This changes the exact angle you're calculating trigonometric values for, and introduces cumulative error over each iteration:
- For example, the second iteration should be exactly
Math.PI/2(~1.5708 radians), but after rounding the first iteration's value and addingMath.PI/4again, you end up with ~1.58 radians instead. - Calculating
cos(1.58)gives you ~-0.01 instead of the expected 0.0, which throws off your output.
Additionally, rounding the angle before computing sin and cos amplifies these precision errors, since you're no longer using the exact unit circle angles.
The Fix: Separate Calculation from Formatting
The solution is to keep your angle values precise for calculations, and only format them when printing. Here's a corrected version of your code:
public class UnitCircle extends ConsoleProgram { public void run() { System.out.println("Radians: (cos, sin)"); // Keep the original precise angle for calculations for(double angle = 0; angle <= 2 * Math.PI; angle += Math.PI / 4) { // Calculate sin/cos using the exact angle double cos = Math.cos(angle); double sin = Math.sin(angle); // Format values to 2 decimal places for output String formattedAngle = String.format("%.2f", angle); String formattedCos = String.format("%.2f", cos); String formattedSin = String.format("%.2f", sin); // Fix cases where we get -0.0 (a quirk of floating-point math) formattedCos = formattedCos.equals("-0.00") ? "0.0" : formattedCos; formattedSin = formattedSin.equals("-0.00") ? "0.0" : formattedSin; // Print in the expected format (all on one line, as shown) System.out.printf("%s: %s, %s ", formattedAngle, formattedCos, formattedSin); } } }
Key Improvements:
- Preserve Exact Angles: The loop variable
anglestays as the precise value (0, π/4, π/2, ..., 2π) soMath.cosandMath.sinuse accurate inputs. - Format Only for Output: We use
String.formatto round values to 2 decimal places after calculating the trigonometric values, not before. - Handle -0.0: Floating-point operations can sometimes produce
-0.0(for example,sin(Math.PI)might give-0.0instead of0.0). We replace these cases to match the expected output.
Alternative with DecimalFormat
If you prefer using DecimalFormat for formatting, here's another working version:
import java.text.DecimalFormat; public class UnitCircle extends ConsoleProgram { public void run() { System.out.println("Radians: (cos, sin)"); DecimalFormat decimalFormatter = new DecimalFormat("#.##"); decimalFormatter.setMinimumFractionDigits(2); // Ensure two decimal places even for .0 for(double angle = 0; angle <= 2 * Math.PI; angle += Math.PI / 4) { double cos = Math.cos(angle); double sin = Math.sin(angle); // Fix -0.0 before formatting cos = (cos == -0.0) ? 0.0 : cos; sin = (sin == -0.0) ? 0.0 : sin; System.out.printf("%s: %s, %s ", decimalFormatter.format(angle), decimalFormatter.format(cos), decimalFormatter.format(sin) ); } } }
Either version will produce output that matches your expected results, with accurate cos and sin values for each unit circle angle.
内容的提问来源于stack exchange,提问作者Plapatine

