2014-10-24 7 views
-3

Я полный новичок. Я написал небольшую программу C# на SharpDevelop. Вот оно:Почему эта небольшая программа на C# на SharpDevelop, которая использует петли «для», не работает?

double i, j; 

for(i=1; i<=30; i+=(1/60)) 
{ 
    for(j=1+1/60; j<=30; j+=(1/60)) 
    { 
     if(Math.Abs(Math.Log(i)/Math.Log(j)-0.63092975357)<=0.00001) 
     { 
      Console.WriteLine("ln("+i+") ln("+j+")"); 
     } 
    } 
} 

     Console.ReadKey(true); 

Моя программа должна найти i и j, для которых ln(i)/ln(j)=0.63092975357 (например) i и j обязательно равны n/60 и m/60 соответственно, где n и m являются положительными целыми числами. (Я знаю, что я могу использовать тип int вместо типа double, но хотел бы, чтобы это работало с типом double.)

Но это не сработает. Когда я нажимаю «Run Project», появляется черный экран, но ничего не происходит ... И SharpDevelop не указывает на какие-либо ошибки ...

Итак, какие ошибки я сделал? И как исправить мою программу?

+1

Предлагаю установить точку останова в первом цикле 'for', пройти через нее и посмотреть, что произойдет. – Stefan

+1

Не знаете, почему вы получаете downvoted, ваша проблема довольно очевидна. см. мой ответ для деталей. –

+0

Сначала вам нужно получить набор значений, которые, как вы знаете, должны привести к желаемому результату. Затем проверьте свою формулу. Если он работает, проблема заключается в значениях 'i',' j'. Если нет, то исправьте формулу. Повторение. –

ответ

4

Целое подразделение.

1/60 = 0 

Необходимо вместо этого 1/60.0d.

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

Когда вы делаете 1/60 вы ожидаете 0.0166666666666667 но Infact 0.

Этот код теперь работает

double i, j; 

for(i=1; i<=30; i+=(1/60d)) 
{ 
    for(j=1+1/60d; j<=30; j+=(1/60d)) 
    { 
     if(Math.Abs(Math.Log(i)/Math.Log(j)-0.63092975357)<=0.00001) 
      Console.WriteLine("ln("+i+") ln("+j+")"); 
    } 
} 

EDIT: * прочертовский Стоит отметить, написание 60d гарантирует, что 60 является двойной тип. Следовательно, ваше подразделение теперь перенастраивает двойной *

+1

Согласен. позвольте мне подробно остановиться на ответе Алекса - литералы (числа) скомпилированы для того, что они представляют (ваш случай: 60 - целое число. Если вы будете писать 60d или 60. с помощью «.», вы дадите компилятору знать, что вы имели в виду двойное значение 60. –

1

Ошибка, которую я вижу здесь, использует 1/60, ожидая, что это будет двойное представление 0.0166 ... Это фактически 0, потому что и 1, и 60 являются целыми числами, и это становится целым делением. Попробуйте использовать 1.0/60.0, 1/60.0 или 1.0/60, 1/60d или любую их комбинацию, и это должно исправить ее, если ваш алгоритм математически корректен.

После того, как вы исправите это, вы можете начать видеть большое количество строк, печатающих некоторые результаты, так как ваша программа не будет завершена до тех пор, пока петли не закончатся, даже подумал, что она уже может печатать множество данных. Вы можете исправить это, добавив переменную флага (bool), чтобы завершить внешний цикл, и break, чтобы завершить внутренний.

0

1/60 выполняет integer division, и в результате он всегда генерирует 0. Он всегда отбрасывает дробную часть.

/ Operator (C# Reference) От

При делении двух целых чисел, результат всегда является целым числом. Например, для результата результатом 7/3 является 2.

Вот почему ваш первый цикл будет похож на;

for(i = 1; i <= 30; i += 0) 

так i никогда не получить увеличилось, он никогда не будет 30, и именно поэтому это создает infinite loop.

В качестве решения вам необходимо использовать деление с плавающей запятой.

for(i = 1; i <= 30; i += (1/60f)) 
{ 
    for(j = 1+1/60f; j <= 30; j += (1/60)) 

Кроме того, на что, я предлагаю вам прочитать Eric Липперт How to debug small programs которые вы можете легко найти то, что неправильно в вашем коде, даже не спрашивая здесь.

+0

@ Downvoter позаботится прокомментировать, по крайней мере, чтобы я мог видеть, где я могу ошибаться? –

1

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

Также, добавляя Console.Write() перед ReadKey, вы можете видеть, когда цикл завершается.

for(var i=1; i<=1800; i++) 
{ 
    for(var j=1; j<=1800; j++) 
    { 
     double di = double(i)/60.0; 
     double dj = double(j)/60.0; 

     if(Math.Abs((Math.Log(di)/Math.Log(dj))-0.63092975357)<=0.00001) 
     { 
      Console.WriteLine("ln("+di+") ln("+dj+")"); 
     } 
    } 
} 

Console.WriteLine("Press any key to continue"); 
Console.ReadKey(true);