2016-07-11 3 views
0

Я пишу функцию, в которой мне приходится вычислять факторные числа и делать операции над ними. Возвращаемое значение функции должно быть длинным, поэтому я думаю, что было бы лучше делать все операции в длинном длинном формате. Если я ошибаюсь, исправьте меня.tgamma() long long typecasting

Функция tgamma() сама по себе возвращает правильное значение в научной нотации. Но значение, возвращаемое tgamma(), иногда на 1 меньше фактического ответа, когда значение, возвращаемое функцией, приписывается как «long long».

int main() 
{ 
std::cout<<"11!:"<<tgamma(12)<<std::endl; 
std::cout<<"12!"<<tgamma(13)<<std::endl; 
std::cout<<"13!"<<tgamma(14)<<std::endl; 
std::cout<<"14!"<<tgamma(15)<<std::endl; 
std::cout<<"15!"<<tgamma(16)<<std::endl; 
std::cout<<"16!"<<tgamma(17)<<std::endl; 
std::cout<<"********************************"<<std::endl; 
std::cout<<"11!:"<<(long long)tgamma(12)<<std::endl; 
std::cout<<"12!"<<(long long)tgamma(13)<<std::endl; 
std::cout<<"13!"<<(long long)tgamma(14)<<std::endl; 
std::cout<<"14!"<<(long long)tgamma(15)<<std::endl; 
std::cout<<"15!"<<(long long)tgamma(16)<<std::endl; 
std::cout<<"16!"<<(long long)tgamma(17)<<std::endl; 
return 0; 
} 

Я получаю следующий вывод:

11!:3.99168e+07 
12!4.79002e+08 
13!6.22702e+09 
14!8.71783e+10 
15!1.30767e+12 
16!2.09228e+13 
******************************** 
11!:39916800 
12!479001599 
13!6227020799 
14!87178291199 
15!1307674367999 
16!20922789888000 

Фактическое значение 15! в соответствии с this site является 1307674368000, но когда я привожу tgamma (16) в длинный, я получаю только 1307674367999. Дело в том, что это несоответствие появляется только для некоторых чисел. Признанный ответ за 16! является правильным - 20922789888000.

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

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

Любые советы о том, как обнаружить это несоответствие в приведённой стоимости и исправить его? Или, может быть, какая-то другая функция, которую я могу использовать?

+0

tgamma работает с числами с плавающей запятой, что может потерять точность. Почему бы вам просто не написать свою собственную факториальную функцию с помощью целых чисел? – jtbandes

+0

«Функция tgamma() сама по себе возвращает правильное значение в научной нотации». - Нет, это не так. C++ имеет чистый дизайн. Значение возвращается как двоичное значение. Научная нотация - текстовый формат, который может применяться при преобразовании двоичного значения в текст. – MSalters

ответ

0

Кастинг от типа с плавающей точкой до усеченного интегрального типа. Попробуйте (long long) roundl(tgammal(xxx)), чтобы избавиться от целочисленной ошибки усечения. Это также использует длинные удвоения, поэтому он может дать вам больше цифр.

#include <math.h> 
#include <iostream> 
int main(){ 
    std::cout<<"11!:"<<(long long)roundl(tgammal(12))<<std::endl; 
    std::cout<<"12!"<<(long long)roundl(tgammal(13))<<std::endl; 
    std::cout<<"13!"<<(long long)roundl(tgammal(14))<<std::endl; 
    std::cout<<"14!"<<(long long)roundl(tgammal(15))<<std::endl; 
    std::cout<<"15!"<<(long long)roundl(tgammal(16))<<std::endl; 
    std::cout<<"16!"<<(long long)roundl(tgammal(17))<<std::endl; 
    std::cout<<"********************************"<<std::endl; 
    std::cout<<"11!:"<<(long long)roundl(tgammal(12))<<std::endl; 
    std::cout<<"12!"<<(long long)roundl(tgammal(13))<<std::endl; 
    std::cout<<"13!"<<(long long)roundl(tgammal(14))<<std::endl; 
    std::cout<<"14!"<<(long long)roundl(tgammal(15))<<std::endl; 
    std::cout<<"15!"<<(long long)roundl(tgammal(16))<<std::endl; 
    std::cout<<"16!"<<(long long)roundl(tgammal(17))<<std::endl; 
    return 0; 
} 

Дает:

11!:39916800 
12!479001600 
13!6227020800 
14!87178291200 
15!1307674368000 
16!20922789888000 
******************************** 
11!:39916800 
12!479001600 
13!6227020800 
14!87178291200 
15!1307674368000 
16!20922789888000 
+0

это помогло мне. Спасибо! –

+0

Почему эта ошибка появляется только для некоторых чисел? Разве это не должно быть однородным, если это ошибка? Почему только 15! typecasted ответ ошибочен, а 16! ответ нет? –

+1

tgamma приблизительный. Кастинг интегрального типа усекает вместо раундов. Использование большего количества цифр и round/roundl поможет с обоими. – evaitl

0

Очевидно, что если мы не имеем очень необычную реализацию, не все длинные длинные числа могут быть точно представлены в два раза. Поэтому tgamma не может хранить двойные значения, так что отливка до долгого времени даст точное значение. Просто в длинном длинном интервале более длинные значения, чем двойные значения.

Если вам нужен точный длинный факториал, вы должны реализовать его самостоятельно.

В дополнение к этому, если вы хотите точности, вы преобразовываете двойное и длинное длинное не как (длинное длинное) x, а как (длинное длинное) круглое (x) или (длинное длинное) (x + 0,5), если х положительно.

+0

приятное объяснение! (Длинный длинный) (tgamma (x) + 0,5) создает более короткий код ... хороший отзыв! –

+0

есть ли какая-либо стандартная функция C++, которая возвращает точный факториал числа без необходимости обхода обходных ошибок при типизации? –

+0

Google для 'std factorial standard library', и вы найдете ответ :) – user31264

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