tgamma()long long typecasting

时间:2016-07-11 04:19:01

标签: c++ numbers c++14 factorial

我正在编写一个函数,我必须计算数字的阶乘并对它们进行操作。函数的返回值应该很长,所以我认为以long long格式执行所有操作会更好。如果我错了,请纠正我。

tgamma()函数本身以科学计数形式返回正确的值。但是当函数返回的值被强制转换为'long long'时,tgamma()返回的值有时比实际答案少1。

 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!根据{{​​3}}是1307674368000,但是当我将tgamma(16)强制转换为long long时,我得到的只是1307674367999.事情是这种差异只出现在一些数字上。 16的答案!是正确的 - 20922789888000。

此功能适用于目前正在进行的竞争性编程问题,因此我无法在此处粘贴我正在开发的功能和解决方案。

我会推出自己的阶乘函数,但我希望减少程序中的字符数以获得奖励积分。

有关如何检测类型差异并纠正错误的任何提示?或者也许我可以使用其他一些功能?

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

显然,除非我们有非常不寻常的实现,否则不是所有的长数都可以精确地表示为double。因此,tgamma不能存储双精度值,以便铸造成long long会产生精确值。在很长的时间间隔内,只需要比长值更长的长值。

如果你想要精确的long long factorial,你应该自己实现它。

除此之外,如果你想要精度,你可以将double变换为long long而不是(long long)x,但是(long long)round(x)或(long long)(x + 0.5),假设x是正面的。