具有相同值但不同类型的参数的 std::floor 函数的不同值
Posted
技术标签:
【中文标题】具有相同值但不同类型的参数的 std::floor 函数的不同值【英文标题】:different values of std::floor function for arguments with same value but different types 【发布时间】:2011-08-11 19:22:49 【问题描述】:考虑以下几点:
#include <iostream>
#include <cmath>
int main()
using std::cout;
using std::endl;
const long double be2 = std::log(2);
cout << std::log(8.0) / be2 << ", " << std::floor(std::log(8.0) / be2)
<< endl;
cout << std::log(8.0L) / be2 << ", " << std::floor(std::log(8.0L) / be2)
<< endl;
输出
3, 2
3, 3
为什么输出不同?我在这里错过了什么?
这里也是键盘的链接:http://codepad.org/baLtYrmy
我在 linux 上使用 gcc 4.5,如果这很重要的话。
【问题讨论】:
仅供参考,Visual C++ 2010 给出:3、3 和 3、3。顺便说一句,我需要执行“std::log(2.0)”而不是“std::log(2)”来避免歧义。 @Branko : VC++ 将long double
视为double
的同义词。
【参考方案1】:
当我添加这个时:
cout.precision(40);
我得到这个输出:
2.999999999999999839754918906642444653698, 2
3.00000000000000010039712117215771058909, 3
您正在打印两个非常接近但不完全等于 3.0 的值。 std::floor
的本质是,对于非常接近的值,它的结果可能会有所不同(从数学上讲,它是一个不连续的函数)。
【讨论】:
【参考方案2】:#include <iostream>
#include <cmath>
#include <iomanip>
int main()
using std::cout;
using std::endl;
const long double be2 = std::log(2);
cout << setprecision (50)<<std::log(8.0)<<"\n";
cout << setprecision (50)<<std::log(8.0L)<<"\n";
cout << setprecision (50)<<std::log(8.0) / be2 << ", " << std::floor(std::log(8.0) / be2)
<< endl;
cout << setprecision (50)<< std::log(8.0L) / be2 << ", " << std::floor(std::log(8.0L) / be2)
<< endl;
return 0;
输出是:
2.0794415416798357476579894864698871970176696777344
2.0794415416798359282860714225549259026593063026667
2.9999999999999998397549189066424446536984760314226, 2
3.0000000000000001003971211721577105890901293605566, 3
如果您检查输出 here,您会注意到两个输出的精度略有不同。这些舍入错误通常会在执行floor()
时在此处对 float 和 double 进行操作,并且出现的结果并不是人们认为应该的那样。
在处理浮点数或双精度数时,记住两个属性 Precision 和 Rounding 很重要。
您可能想在我的回答 here 中了解更多相关信息,同样的推理也适用于此。
【讨论】:
我看不出输出有什么不同【参考方案3】:扩展 Als 所说的内容-
在第一种情况下,您将 8 字节双精度值除以 16 字节长双精度值。在第二种情况下,您将 16 字节长双精度除以 16 字节长双精度。这会导致一个非常小的舍入误差,可以在此处看到:
cout << std::setprecision(20) << (std::log(8.0) / be2) << std::endl;
cout << std::setprecision(20) << (std::log(8.0L) / be2) << std::endl;
产生:
2.9999999999999998398
3.0000000000000001004
编辑说:在这种情况下, sizeof 是你的朋友(查看精度差异):
sizeof(std::log(8.0)); // 8
sizeof(std::log(8.0L)); // 16
sizeof(be2); // 16
【讨论】:
8 位双打?是不是打错字了?以上是关于具有相同值但不同类型的参数的 std::floor 函数的不同值的主要内容,如果未能解决你的问题,请参考以下文章
带有 ggplots 的 for 循环生成具有相同值但标题不同的图形
如何使用相同的值但使用现有字段之一的不同数据类型来注释 Django Queryset?
如何删除具有相同属性值但在 NSMutableArray 中有一个的所有对象