我可以使用long double来计算C语言中的整数吗

时间:2018-11-20 06:11:20

标签: c factorial long-double

我尝试编写一个阶乘函数来计算一个大数(factorial(105)),其结果为168位,因此请使用long double,但这似乎是一个错误,不能这样使用吗? / p>

**Use this code to authenticate and upload a file. You need to set <YOUR_REGISTERED_REDIRECT_URI> (and also in console) to this document itself to authenticate.By this way you can upload the file**

require_once 'Google/Client.php';
require_once 'Google/Service/Drive.php';

$client = new Google_Client();
// Get your credentials from the console
$client->setClientId('<YOUR_CLIENT_ID>');
$client->setClientSecret('<YOUR_CLIENT_SECRET>');
$client->setRedirectUri('<YOUR_REGISTERED_REDIRECT_URI>');
$client->setScopes(array('https://www.googleapis.com/auth/drive.file'));

session_start();

if (isset($_GET['code']) || (isset($_SESSION['access_token']) && $_SESSION['access_token'])) {
    if (isset($_GET['code'])) {
        $client->authenticate($_GET['code']);
        $_SESSION['access_token'] = $client->getAccessToken();
    } else
        $client->setAccessToken($_SESSION['access_token']);

    $service = new Google_Service_Drive($client);

    //Insert a file
    $file = new Google_Service_Drive_DriveFile();
    $file->setName(uniqid().'.jpg');
    $file->setDescription('A test document');
    $file->setMimeType('image/jpeg');

    $data = file_get_contents('a.jpg');

    $createdFile = $service->files->create($file, array(
          'data' => $data,
          'mimeType' => 'image/jpeg',
          'uploadType' => 'multipart'
        ));

    print_r($createdFile);

} else {
    $authUrl = $client->createAuthUrl();
    header('Location: ' . $authUrl);
    exit();
}

3 个答案:

答案 0 :(得分:5)

信封背面的计算:25!略大于10 25 ;三个数量级大约是10位,因此即使只是精确表示结果,您也需要大约83位尾数。

假设long double在支持它的平台上通常是整个值的80位(不仅仅是尾数!),显然您没有足够的尾数来以整数精度执行该数量级的计算。

但是:阶乘在这里有点魔术,因为许多因子包含2的幂,它们只需在右边添加二进制零,不需要尾数(它们以指数结尾) )。特别是:

25! = 2   4   2   8   2    4    2    16    2    4     2    8    = 2²² · m
        3   5 3 7   9 5 11 3 13 7 15    17 9 19 5 21 11 23 3 25 

(m是所有非2因子的乘积,即m = 3 10 ·5 6 ·7 3 ·11 < sup> 2 ·13·17·19·23,因此有效地我们必须存储在尾数中的数据

因此,我们的初步估算超出了实际要求22位。

事实证明

log 2 (f)= 10·log 2 3 + 6·log 2 5 + 3·log 2 < / sub> 7 + 2·log 2 11 + log 2 13 + log 2 17 + log 2 19 + log 2 23 = 61.68

的确小于80位长双精度数(64位)的尾数大小。但是,当您将其乘以26(因此,不包括因数2,该因数最终在指数中乘以13)时,您将添加log2(13)= 3.7位。 61.7 + 3.7是65.4,所以从26开始!此后,您将不再具有精确执行计算的精度。

答案 1 :(得分:3)

首先,没有人知道long double可以代表什么或不能代表什么。格式的具体属性取决于实现。

第二,X86扩展精度浮点格式具有64位有效数字,带有显式前导1,这意味着它可以表示±2 64 范围内的连续整数。超出该范围的可表示整数是不连续的(即,它们开始以越来越大的间隙“跳过”)。您的阶乘不在此范围之内,这意味着完全可以期望它们不会被精确表示。

答案 2 :(得分:3)

自105年以来!是一个巨大的数字,它不适合单个单词(或其中两个单词),您需要arbitrary precision arithmetic,也称为 bignum 。使用Stirling's approximation了解105的大小!是,并阅读factorials上的维基页面。

标准C(请阅读n1570进行检查)本来就没有bignums,但是您会发现很多库。

我推荐GMPlib。顺便说一句,出于性能原因,它的某些代码是手写汇编(当对bignum加法编码时,您希望利用 add带有机器指令进行加法)。

我建议避免编写自己的bignum操作。现有的库使用非常聪明的算法(您需要做一些博士工作才能获得更好的结果)。如果您尝试编写自己的bignum库,则它可能会比竞争对手差很多(除非您花费多年的工作时间)。