2017-01-05 5 views
0

Так что я беру курс онлайн Java, и задача заключается в следующем:(Java) Моя единичная окружность программа производит странный результат

В этой программе мы будем практиковать, используя класс Math, вычисляя некоторые важные значения на единичном круге. Начиная с 0 и поднимаясь на PI/4 радианов (или 45 градусов), распечатайте информацию в следующем формате.

Radians: (cos, sin) 
    0.0: 1.0, 0.0 
    0.79: 0.7, 0.71 
    1.57: 0.0, 1.0 
    2.36: -0.71, 0.7 
    3.14: -1.0, 0.0 
    3.93: -0.7, -0.71 
    4.71: 0.0, -1.0 
    5.5: 0.71, -0.71 

Подсказка: Вы должны использовать Math.sin, методы Math.cos и постоянную Math.PI! Вам также необходимо в цикле от 0 до 2 * PI

Вот что я придумал:

public class UnitCircle extends ConsoleProgram 
    { 
     public void run() 
     { 
      System.out.println("Radians: (cos, sin)"); 
      for(double count = 0; count <= Math.PI * 2; count += Math.PI/4) 
      { 
       System.out.println(count + ": " + Math.cos(count) + ", " + Math.sin(count)); 
      } 
     } 
    } 

Однако, когда я запускаю его, это то, что я получаю:

Radians: (cos, sin) 
    0.0: 1.0, 0.0 
    0.7853981633974483: 0.7071067811865476, 0.7071067811865475 
    1.5707963267948966: 6.123233995736766E-17, 1.0 
    2.356194490192345: -0.7071067811865475, 0.7071067811865476 
    3.141592653589793: -1.0, 1.2246467991473532E-16 
    3.9269908169872414: -0.7071067811865477, -0.7071067811865475 
    4.71238898038469: -1.8369701987210297E-16, -1.0 
    5.497787143782138: 0.7071067811865474, -0.7071067811865477 
    6.283185307179586: 1.0, -2.4492935982947064E-16 

Что случилось? Может быть, мне нужно ограничить вычисления округлением до двух знаков после запятой? Что еще я делаю неправильно? Любая помощь будет принята с благодарностью.

+0

«Может быть, мне нужно ограничить вычисления округлением до двух знаков после запятой?» Да. Я не знаю, почему результаты этого примера показывают разные количества значимых цифр для 'sin (PI/4)' и 'cos (PI/4)', поскольку они должны быть почти одинаковыми, что видно из вашего '0.7071067811865476, 0.7071067811865475 'output - игнорировать этот образец и придерживаться двух знаков после запятой, я бы посоветовал. –

ответ

0

Простейшим решением является форматирование вывода с использованием простого оператора печати: System.out.format ("%. 2f:% .2f,% .2f"); Это просто и позволит вам двигаться дальше, но всегда есть больше, чтобы узнать как о номерах форматирования, так и о том, как машины представляют числа!

Проблема форматирования заключается в том, что неявный процесс преобразования, используемый в операторах System.out.println, не соответствует целям округления и интервалов. Мы хотим контролировать этот процесс форматирования для получения более чистого результата. Обратите внимание, что форматирование вывода строки с помощью усечения в стиле printf является немного иной концепцией, чем округление. Округление происходит с помощью явного оператора округления, такого как Math.round, или класса типа NumericFormat или DecimalFormat. Комментарии уже указывают на хорошую ссылку на SO для форматирования чисел. Документация Oracle в Интернете содержит более подробную информацию: https://docs.oracle.com/javase/7/docs/api/java/text/DecimalFormat.html

Более интересная проблема связана с тем, как машины (и JVM) хранят и вычисляют числовые значения. Посмотрите на прототипы метода; оба метода Math.cos и Math.sin возвращают двойной. Это один из примитивных типов Java, используемых для представления числовых значений. Машины представляют и выполняют математические операции с числовыми значениями, не совсем совершенны.

Java double основан на стандарте (IEEE754), который указывает конкретное использование 64 бит для представления числа. Удваивает, что поплавки используются в машинах для представления действительных чисел (считайте непрерывные значения, а не только целые числа). Нетрудно заметить, что 64-битное значение не может идеально представлять все действительные числа; существует бесконечное число реальных значений, но только 2^64 уникальных двойников. Существует стандарт для float, который использует только 32 бита для представления всех действительных чисел. Это означает, что между фактическим значением и представленными значениями могут быть различия. Можно увидеть различия между значениями, которые фактически идентичны при вычислении по-разному (например, Math.sin (Math.PI/4) == Math.cos (Math.PI/4)). Разница между истинными и представленными значениями настолько мала, чтобы не повлиять на приложение.

Смежные вопросы