我尝试编写一个阶乘函数来计算一个大数(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();
}
答案 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库,则它可能会比竞争对手差很多(除非您花费多年的工作时间)。