2017-02-10 20 views
1

Я работаю над этим очень простым и базовым скриптом на стр. 66 «Sams Teach Yourself C Programming».неправильный математический вывод в C

В принципе, сценарий запрашивает у вас некоторое количество секунд.
Вы вводите число, затем вычисляет количество часов и секунд, которые они составляют.

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

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

И, наконец, в самом конце я добавил комментарии, чтобы проиллюстрировать несколько очень дурацких выходов.

**** показывает инкрементный исследование подсчета **** **** указывает на резкое изменение выходного сигнала в ответ на очень небольшое изменение на входе (т.е. 1 цифра).

Впервые я заметил проблему, когда я случайно вводил 85000000.

Я приложил все усилия, чтобы упорядочить код, чтобы было легче сосредоточиться на математике.
Я не уверен, что это математическая проблема или опечатка.

Во всяком случае, вот код:

/* Illustrates the modulus operator. */ 
/* inputs a number of seconds, and converts to hours, minutes, and seconds. */ 
// minute = 60 seconds     : 60 
// hour = 60 * 60 seconds    : 3600 
// day = 24 * 60 * 60 seconds   : 86400 
// year = 365 * 24 * 60 * 60 seconds : 31536000 

#include <stdio.h>          // from original script 

/* Define constants */ 

#define SECS_PER_MIN 60         // from original script 
#define MIN_PER_HOUR 60 
#define HOURS_PER_DAY 24 
#define DAYS_PER_YEAR 365 
#define SECS_PER_YEAR 31536000 
#define SECS_PER_HOUR 3600        // from original script 
#define SECS_PER_DAY 86400 
#define LIMIT 2147438647 

unsigned int seconds, minutes, hours, days, years, secs_remain, mins_remain, hours_remain, days_remain;  // modified from original script 

int main(void)                       // from original script 
{ 
    seconds = minutes = hours = days = years = secs_remain = mins_remain = hours_remain = days_remain = 0; 
    /* Input the number of seconds. */ 

    printf("Enter the number of seconds (> 0, < %u): \n", LIMIT);     // modified from original script 
    scanf("%d", &seconds);                   // from original script 

    years = seconds /SECS_PER_YEAR; 
    days = seconds/SECS_PER_DAY; 
    hours = seconds/SECS_PER_HOUR;                 // from original script 
    minutes = seconds/SECS_PER_MIN;                 // from original script 
    days_remain = days/DAYS_PER_YEAR;  // ***missing 22643200 seconds, given input: 85000000*** 
    hours_remain = hours % HOURS_PER_DAY; 
    mins_remain = minutes % MIN_PER_HOUR;                // modified from original script 
    secs_remain = seconds % SECS_PER_MIN;                // from original script 

    printf("%u seconds is equal to ", seconds);              // from original script 

    if (seconds < SECS_PER_HOUR) 
    { 
     printf("%u m, and %u s\n", minutes, secs_remain); 
     return 0; 
    } 
     else if((seconds >= SECS_PER_HOUR) && (seconds < SECS_PER_DAY)) 
     { 
       printf("%u h, %u m, and %u s\n", hours, mins_remain, secs_remain);     // from original script 
       return 0;                    // from original script 
     }  
     else if((seconds >= SECS_PER_DAY) && (seconds < SECS_PER_YEAR)) 
     { 
       printf("%u d, %u h, %u m, and %u s\n", days, hours_remain, mins_remain, secs_remain); 
       return 0; 
     }    
     else if((seconds >= SECS_PER_YEAR) && (seconds < LIMIT)) 
     { 
      printf("%u y %u d, %u h, %u m, and %u s\n", years, days_remain, hours_remain, mins_remain, secs_remain); // calculation day's inaccurate 
      return 0; 
     } 
     else if(seconds > LIMIT) 
     { 
      printf("error: excessive amount of seconds.\n"); 
      printf("range for seconds must be between 0 and %u!\n", LIMIT); 
      printf("If number of seconds exceeds %u, then it is beyond range for type 'int'.\n", LIMIT); 
      printf("EXITING seconds program. \n"); 
      return 1; 
     } 
    } 

// ERROR: 31536000 seconds is equal to 1 y 1 d, 0 h, 0 m, and 0 s 
// ERROR: 63072000 seconds is equal to 2 y 2 d, 0 h, 0 m, and 0 s 
// ERROR: 70000000 seconds is equal to 2 y 2 d, 4 h, 26 m, and 40 s       **** 
// ERROR: 78840000 seconds is equal to 2 y 2 d, 12 h, 0 m, and 0 s       **** 
// ERROR: 90000000 seconds is equal to 2 y 2 d, 16 h, 0 m, and 0 s       **** 
// ERROR: 92500000 seconds is equal to 2 y 2 d, 14 h, 26 m, and 40 s      **** 
// ERROR: 93750000 seconds is equal to 2 y 2 d, 1 h, 40 m, and 0 s       **** 
// ERROR: 94380000 seconds is equal to 2 y 2 d, 8 h, 40 m, and 0 s       **** 
// ERROR: 94537500 seconds is equal to 2 y 2 d, 4 h, 25 m, and 0 s       **** 
// ERROR: 94576875 seconds is equal to 2 y 2 d, 15 h, 21 m, and 15 s      **** 
// ERROR: 94596562 seconds is equal to 2 y 2 d, 20 h, 49 m, and 22 s      **** 
// ERROR: 94606406 seconds is equal to 2 y 2 d, 23 h, 33 m, and 26 s      **** 
// ERROR: 94607636 seconds is equal to 2 y 2 d, 23 h, 53 m, and 56 s      **** 
// ERROR: 94607943 seconds is equal to 2 y 2 d, 23 h, 59 m, and 3 s       **** 
// ERROR: 94607981 seconds is equal to 2 y 2 d, 23 h, 59 m, and 41 s      **** 
// ERROR: 94607990 seconds is equal to 2 y 2 d, 23 h, 59 m, and 50 s      **** 
// ERROR: 94607995 seconds is equal to 2 y 2 d, 23 h, 59 m, and 55 s      **** 
// ERROR: 94607998 seconds is equal to 2 y 2 d, 23 h, 59 m, and 58 s      **** 
// ERROR: 94607999 seconds is equal to 2 y 2 d, 23 h, 59 m, and 59 s      **** **** 
// ERROR: 94608000 seconds is equal to 3 y 3 d, 0 h, 0 m, and 0 s       **** **** 
// ERROR: 94608174 seconds is equal to 3 y 3 d, 0 h, 2 m, and 54 s       **** 
// ERROR: 94608097 seconds is equal to 3 y 3 d, 0 h, 1 m, and 37 s       **** 
// ERROR: 94608251 seconds is equal to 3 y 3 d, 0 h, 4 m, and 11 s       **** 
// ERROR: 94608867 seconds is equal to 3 y 3 d, 0 h, 14 m, and 27 s       **** 
// ERROR: 94611328 seconds is equal to 3 y 3 d, 0 h, 55 m, and 28 s       **** 
// ERROR: 94616250 seconds is equal to 3 y 3 d, 2 h, 17 m, and 30 s       **** 
// ERROR: 94695000 seconds is equal to 3 y 3 d, 0 h, 10 m, and 0 s       **** 
// ERROR: 95000000 seconds is equal to 3 y 3 d, 12 h, 53 m, and 20 s      **** 
// ERROR: 100000000 seconds is equal to 3 y 3 d, 9 h, 46 m, and 40 s      **** 
// ERROR: 122990400 seconds is equal to 3 y 3 d, 12 h, 0 m, and 0 s 
// ERROR: 126144000 seconds is equal to 4 y 4 d, 0 h, 0 m, and 0 s 
+3

Посмотрите на эту строку 'days_remain'. Разве это не выглядит иначе? – user2357112

+1

Знаете ли вы, какое целочисленное усечение в результате деления есть? –

+0

@ пользователь2357112, спасибо. Я изменил этот оператор «/» на «%» в строке: 35, и проблема, похоже, решена. – Vasqi

ответ

2

In Your Line Code,

days_remain = days/DAYS_PER_YEAR; // ***missing 22643200 seconds, given input: 85000000*** 

Здесь она должна быть % Вместо того /, вы ошибочно Письменное некорректным.

Также когда я увидел эту часть вашего кода, я бы Сомнение Может быть это не будет работать

else if(seconds > LIMIT) 
      { 
       printf("error: excessive amount of seconds.\n"); 
       printf("range for seconds must be between 0 and %u!\n", LIMIT); 
       printf("If number of seconds exceeds %u, then it is beyond range for type 'int'.\n", LIMIT); 
       printf("EXITING seconds program. \n"); 
       return 1; 
       } 

Пожалуйста, ознакомьтесь Validate max integer in scanf Чтобы посмотреть, как проверить ввод заданного пользователем.

+0

Вы правы, что последняя часть не работает (как и ожидалось). чтобы увидеть, что произойдет, если я введу значение, превышающее диапазон для типа int, но если ничего не получилось, тогда я хотел бы предоставить ему средство продемонстрировать, что чрезмерное значение было принято (несмотря на то, что оно выходит за пределы диапазона) – Vasqi

+0

Фактический результат состоял в том, что чрезмерная ценность была фактически принята, назначена и отображена. – Vasqi

+0

Не может быть того, что является чрезмерным значением, что вы ввели, а также вы принимаете входные данные с% d и печать с% u why? –

1

Редактировать свой код: days_remain = days% DAYS_PER_YEAR;