Разные выходные данные для одного и того же алгоритма на разных языках

#java #c #algorithm

#java #c #алгоритм

Вопрос:

Исходный код Java:

 package n1_problem;

/**
 *
 * @author nAwS
 */
public class loop {

    int loop(long i)
    {
        long n=i;
        int count=1;
        while(n>1){
            if(n%2==0){
                n=n/2;
            }
            else{
                n=3*n 1;
            }
            count  ;
        }
       return count; 
    }

    int max_cycle(long j,long k){

        int max=-1;
        for(long i=j;i<=k;i  ){
            int count=loop(i);
            if(count>max){
                max=count;
            }
        }
        return max;
    }


}


public class Main {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {

        loop lp=new loop();
        System.out.println("Max Cycle:" lp.max_cycle(1,1000000));
    }

}
  

Исходный код C:

 int main()
{
    long r,h;
    int f=0;
    do 
    {
        printf("Value,r:");
        scanf("%ld",amp;r);
        printf("Value,h:");
        scanf("%ld",amp;h);

        f=max_cycle(r,h);
        printf("Max:%dn",f);

    }while(getch()!='e');
}

int loop(long i)
{
        long n=i;
        int count=1;
        while(n>1)
        {
            if(n%2==0){
                n=n/2;
            }
            else{
                n=3*n 1;
            }
            count  ;
        }
       return count; 
    }

    int max_cycle(long j,long k)
    {

        int max=1;
        long i=0;
        for(i=j;i<=k;i  ){

            int count=loop(i);
            if(count>max){
                max=count;
            }
        }
        return max;
    }
  

Нет логической разницы между этими двумя кодами для алгоритма задачи 3n 1.Единственная проблема в том, что в C это дает 476 в качестве максимального номера цикла, тогда как в java это 525 … почему??

Комментарии:

1. Я подозреваю, что ваш код вызывает неопределенное поведение из-за переполнения со знаком.

Ответ №1:

В большинстве компиляторов C long обычно определяется как 4-байтовое целое число (сокращение от long int ). В Java long определяется как 8-байтовое целое число.

Вы можете изменить свой Java-код, чтобы использовать int для 4-байтового целого числа, или использовать long long в вашей программе c для 8-байтового целого числа (я думаю, это было добавлено в C99, оно может быть доступно в вашем компиляторе, а может и нет).

Комментарии:

1. верно, технически диапазон указан, но на самом деле не имеет особого смысла реализовывать его каким-либо другим способом.

2. В C, long s не являются «обычно» 4-байтовыми. Они имеют как минимум 32 бита и обычно 32 или 64 (например, в x86_64-linux-gnu). В любом случае, если вы заботитесь о получении правильного размера целого числа, вы не угадываете волшебным образом правильное количество long s для добавления, вы используете stdint.h или эквивалентный заголовок pre-C99.

Ответ №2:

Java определяет размер и представление целочисленных типов, C этого не делает. В Java long — это 64-разрядный номер дополнения 2. В C это как минимум 32 бита, возможно, больше, и может быть подписанным, беззнаковым, дополнением 1, дополнением 2, знаком и величиной или другим.

Вы заметили, что если вы измените эту строку вашего Java-кода

 long n = i;
  

к этому

 int n = (int)i;
  

Что вы получаете тот же результат, что и ваш C-код? Возможно, вы работаете на двухкомпонентной машине, и ваш компилятор C решил, что long s — это 32 бита.

Комментарии:

1. Наконец-то!.. Я понял!… использование unsigned long дает правильный результат …:)

Ответ №3:

В Java коде, в методе max_cycle(long j,long k) , max инициализируется значением -1, где, как и в C коде, оно равно 1. Просто проверьте, не вызывает ли это логическую ошибку.