2015-01-18 2 views
1

Я запускаю программу ниже и получаю неожиданный номер на выходе.Нужно объяснение вывода программы C

Введите число, чтобы проверить

1410065407 простое число

я получаю различное число на выходе. Я вошел в 9999999999, и я вижу 1410065407 на выходе. Может кто-нибудь объяснить, как это происходит? Похоже, я превосхожу диапазон целочисленного домена.

#include<stdio.h> 
#include<stdlib.h> 
void main() 
{ 

    int n,i; 

    printf("Enter the number to be checked\n"); 

    scanf("%d",&n); 

    i=2; 

    while(i<n) 
    { 
     if(n%i==0) 
     { 
      printf("%d is not a prime number\n", n); 
      exit(0); 
     } 

     i++; 
    } 

    printf("%d is a prime number\n", n); 

} 
+1

'void main()' должен быть 'int main (void)'. Если вы узнали 'void main()' из книги, верните свои деньги и пожалотесь издателю. –

ответ

3

9,999,999,999 (десять 9 s) является большим, чтобы вписаться в ваш тип int данных. Если вы работаете разницу между этим и 1,410,065,407, вы увидите, что это точная мощность двух (2 быть точным), а это означает, что она обернута вокруг, пока вы сканировали его.

К «завернутые вокруг ", я ссылаюсь на свойство целых чисел, чтобы просто обернуть их с максимальным значением, чтобы стать чем-то неожиданным.

Например, восьмизначное целое число без знака, которое может содержать значения 0..255, при добавлении одного к переменной, удерживающей 255, станет нулевым (значения в значении имеют тенденцию обертываться от наибольшего положительного значения до наименьшего отрицательного значения, наименьший смысл, далекий от нуля в этом случае).

Итак, скажем, вы читаете десятичное число, где тип имеет диапазон 0..255, а строковое представление числа - 456. Следующий «код» будет примерно, как она работает:

def scanNum(s): 
    result = 0 
    for each character c in s: 
     result = result * 10 + value(c) 
    return result 
  • При обработке 4 характера, result умножается на десять, 0 * 10 = 0, а затем добавить четыре, давая 4.
  • При обработке символа 5result умножается на десять, 4 * 10 = 40, а затем вы добавляете пять, давая 45.
  • При обработке 6 характера, result умножаются на десять, 45 * 10 = 450но, потому что вы можете только представить 0..255, он оборачивается вокруг, давая вам 450 - 256 = 194. А затем добавьте шесть, давая 200.

Вы можете видеть, что разница между тем, что вы хотите и что получаете, очень сильно зависит от диапазона: 456 - 200 = 256.

Если вы попробуете это с девять9 с (или 999,999,999, имея в виду наибольшее число представимо с 32-битным дополнением до двух больше на 2,147,483,647), или использовать тип данных, способный удерживать большее количество, вы» будет, вероятно, найти это нормально:

#include <stdio.h> 
#include <stdlib.h> 
int main (void) { 
    long long n; 
    printf("Enter the number to be checked\n"); 
    scanf("%lld",&n); 
    printf("%lld\n", n); 
    return 0; 
} 

первоначально я думал, что это было неправильно в соответствии со стандартом, так как, согласно C11 7.21.6.2 The fscanf function /12, оно сдвинуто на strtol функции:

d Соответствует значению десятичного целого числа, форма которого совпадает с ожидаемым для субъектной последовательности функции strtol со значением 10 для базового аргумента. Соответствующим аргументом должен быть указатель на целое число со знаком.

и функция strtol, C11 7.22.1.4 The strtol, strtoll, strtoul, and strtoull functions /8 состояния:

Если правильное значение находится вне диапазона представимых значений, LONG_MIN, LONG_MAX, LLONG_MIN, LLONG_MAX, ULONG_MAX или ULLONG_MAX является возврат (в соответствии с тип возврата и знак значения, если таковые имеются).

Но, в действительности, только формат сдвинуто этой функции. результат для fscanf и его братьев контролируется C11 7.21.6.2 The fscanf function /10:

Если этот объект не имеет соответствующий тип, или , если результат преобразования не могут быть представлены в объекте, поведение не определено ,

Таким образом, число вы получите обратно, если он находится вне диапазона может быть что угодно, и, на самом деле, учитывая отсутствие ограничений по результатам неопределенного поведения, это может сделать ничего, а не просто возвращение изворотливого результат, в том числе форматирование ваших дисков и сворачивание локального пространства-времени в голые особенности :-)

В этом случае он просто просто переносит значение вокруг как часть процесса сканирования, что является самым простым для кода ,

+0

Да. Разница составляет 8589934592 \t, которая является точной мощностью 2. Но я не получил термин «обернутый вокруг». Вы имеете в виду, что он возвращается к началу целочисленного списка, когда он достигает предела? – Zack

+0

@ Зак, да, это по существу это. Я обновил ответ (по существу) больше информации. Надеюсь, это поможет. – paxdiablo

+0

Большое спасибо за подробный ответ. – Zack

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