2014-01-11 4 views
4

Я написал рекурсивную функцию в C, чтобы обратить целое число (123 -> 321), которое отлично работало, когда я запускал его на своем Mac, но ведет себя странно, когда мой инструктор запускал его на ней компьютер под управлением Windows.C-программа, дающая разные результаты по OSX и окнам

int rev(int num) 
{ 
    int base; 

    if (num < 10) return (num); 

    base = pow(10,(int)log10(num)); 
    return(rev(num/10)+num%10*base); 
} 

К примеру, на OSX вызова Rev (8765) возвращает 5678, на Windows, Rev (8765) возвращает 5672. У меня нет доступа к компьютеру Windows, чтобы попытаться запустить программу в режиме отладки, поэтому мне было трудно попытаться угадать, в чем проблема. Я был бы очень признателен за понимание!

Окружающая среда:

Я использую с помощью OSX 10.8 и GCC 4.2. Я почти уверен, что мой инструктор использует MinGW в качестве своего компилятора.

+0

Какой компилятор использовался на стороне Windows? – kmort

+0

Она использует Dev C++, и я думаю, что MinGW поставляется с этим по умолчанию. – ezig

+0

Не используйте плавающие точки для таких вещей, если вы не являетесь экспертом по численному анализу. –

ответ

6

pow и log10 не должны быть правильно закруглены; результаты, полученные ими, могут и будут отличаться между платформами, даже для случаев, которые «должны быть» точными, как в вашем примере. В этом случае OS X дает более точный результат, чем Windows, что приводит к ошибкам, которые появляются только на выходе Windows.

гораздо лучшее решения было бы использовать повторное деление и умножение на 10 в целом, а не использовать с плавающей точкой на всех (есть очень чистое рекурсивное решение похоже на ваш, не требуя, чтобы вы вычислить base) ,


Как и в сторону, мини-декламация: Это зазорным, что так много математические библиотеки не правильно обрабатывать небольшие силы десять и два в log10, log2, exp2 и pow. Нетрудно спроектировать эти функции таким образом, чтобы они делали «правильную вещь» для этих случаев, и это можно сделать, не отрицательно влияя на работу других случаев. Хотя стандарт не требуется, это простое дело, и это помогает экономить неопытных программистов от (исключительно распространенных) ошибок, подобных этому.

+1

Спасибо! Я понял, что это проблема с плавающими очками. – ezig

+0

+1 Хорошее объяснение, и мне понравилась * позорная * часть. –

+0

Я не уверен, как обычно можно сказать, что особые случаи для степеней десяти для 'pow()' не оказывают отрицательного влияния на остальную часть функции (в аспектах, отличных от производительности). Возможно, разработчики функции '' pow() 'очень гордятся тем, что создали такую ​​функцию, что' pow (0xA.0000000000008p0, 2) 'больше, чем' pow (10, 2) ', то же, что и с математической функцией , и что это свойство будет нарушено, если они обладают специальными значениями целых чисел. Мне кажется, что правильный способ сделать неудивительный 'pow()' состоит в том, чтобы сделать его точным для одного ulp, а не для особых случаев. –

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