2015-02-27 9 views
4

Я работаю над программой Java, которая выводит синусоидальную волну на консоль. Это то, что я написал до сих пор:Печать синусоидальной волны на консоли

int num = 7; 
for (double y = 2; y >= 0; y-=0.2) { 
    for (double x = 0; x <= num; x+=0.2) { 
    if (((0.1+x) >= Math.asin((double)y-1)) && (((double)x-0.1) <= Math.asin((double)y-1))) 
     System.out.print('*'); 
    else 
     System.out.print(' '); 
    } 
    System.out.println(); 
} 

По сути, эта программа обрабатывает каждый символ в каждой строке в виде 0,2 х 0,2 областей на координатной плоскости. Если функция синуса пересекает эту область, на экран выводится звездочка. В противном случае будет напечатано пространство. При запуске, это выводится на консоль:

 *       
    *        
    *        
    *         
*         
*         

Может кто-нибудь сказать мне, почему моя программа останавливается после печати первой четверти волны?

+1

Это происходит потому, что 'asin' никогда не дает вам обратно значение вне -pi..pi. 'sin', с другой стороны, является периодическим, поэтому вы можете попробовать его использовать ([demo] (http://ideone.com/YsCaOF)). – dasblinkenlight

+0

Хорошо! Поэтому я подходил к этому с неправильного угла. Спасибо за демо! – coderPro97

ответ

0

Причина, выводит только первую четверть синусоидальной волны из-за указанный range of Math.asin:

Возвращает арксинус значения; возвращаемый угол находится в диапазоне от -pi/2 до pi/2.

После того, как вы заранее x мимо Math.PI/2, то состояние if заявления, будет всегда false.

Вы можете воспользоваться тем, что

грех (я - х) = грех (х)

и

грех (2л - х) = - sin (x)

путем включения дополнительных условий.(Я также удалил ненужные слепки с double для ясности.)

if ((0.1+x >= Math.asin(y-1)) && (x-0.1 <= Math.asin(y-1)) || 
    (0.1+x >= Math.PI - Math.asin(y-1)) && (x-0.1 <= Math.PI - Math.asin(y-1)) 
    (2*Math.PI -(0.1 + x) <= -Math.asin(y-1)) && (2*Math.PI -(x-0.1) >= -Math.asin(y-1)) ) 

Выход:

 *       
    *  *      
    *  *      
    *   *     * 
*    *    * 
*    *    * 
       *   *  
        *   *  
        *  *  
        *  *  
         *   
+0

Этот if-statement определенно лучше, чем тот, который я написал - он работает. Но, если бы я хотел расширить график еще больше, мне нужно было бы добавить еще больше условий. Должен быть более эффективный способ расширения графика без повторного добавления в if-statement. – coderPro97

+1

Да, вы можете расширить его за пределы текущего диапазона. Используйте тот факт, что sin (2π + _x_) = sin (_x_) и выполняйте свою математику (mod 2π). Внутри циклов используйте «double x2pi = x% (2 * Math.PI)», затем выполните оператор 'if', используя' x2pi'. – rgettman

0

Редактировать: Огонь, снял код слишком быстро. Это не верно.

Ну, вы установили num в 7, затем в вашем цикле вы берете x от 0 до num-1, так что вы только зацикливаете на 7 столбцов. Увеличьте число, и ваш график должен добавить дополнительные столбцы. Вам нужно будет увеличить диапазон значений y, которые вы тоже зацикливаете, если вы хотите, чтобы график расширялся до отрицательных чисел.

Однако ваш алгоритм крайне неэффективен. Вы вычисляете asin(y-1) два раза за каждый квадрат на вашем графике, когда вам нужно всего лишь рассчитать sin(x) для каждого столбца. Почему бы просто не заполнить массив с предварительно рассчитанными значениями синуса, а затем обратиться к массиву при рисовании графика? (Я понимаю, конечно, что на современном компьютере это достаточно быстро, чтобы быть практически нерелевантным в любом случае.)

+0

Спасибо за ответ! Да, 'num' = 7, но мой цикл увеличивается на 0,2, поэтому он должен покрывать чуть более одного периода волны. Идея массива умна, я думаю, что я могу попытаться решить эту проблему с этой точки зрения. – coderPro97

+0

@ coderPro97: Если этот ответ решил вашу проблему, вы можете принять его, нажав зеленую галочку. Это позволяет другим пользователям понять, что на вопрос уже был дан удовлетворительный ответ. – user1618143

+0

'num' не имеет к этому никакого отношения. Думаю. x увеличивается на 0,2, поэтому существует гораздо больше 7 циклов ... Правильный ответ дается в комментариях dasblinkenlight – fishi

0

Проблема, похоже, возникает из условия вашего if-утверждения, которое почти всегда оценивается до false. Вы должны проверить исчисление за условным выражением. Я нахожу, что увеличение num здесь действительно не помогает.

Возможно, вам нужно напечатать другой символ вместо пробела, заменив, например, System.out.print(' '); на System.out.print('_');. Таким образом, вы сможете понять, почему ваша программа ведет себя так. Повторное использование этого алгоритма может также быть полезным.

+0

Я думаю, что if-statement должен быть ложным 90% времени. В противном случае функция будет очень нечеткой. Спасибо за ваш ответ! – coderPro97

0

Спасибо всем за помощь! На основании предложения @ dasblinkenlight на использование грех вместо асин, я нашел очень простое решение:

int num = 7; 
for (double y = 1; y >= -1; y-=0.2) { 
    for (double x = 0; x <= num; x+=0.2) { 
    double sin = Math.sin(x); 
    if ((0.1+y) >= sin && (y-0.1) <= sin) 
     System.out.print('*'); 
    else 
     System.out.print(' '); 
    } 
    System.out.println(); 
} 

Печатает на консоль: не

 *****       
    **  *      
    *  **      
    *   *     ** 
*    *    * 
*    *    * 
       *   *  
        *   *  
        *  *  
        ** **  
         ****