del*_*rst 4 c++ algorithm math floating-point floating-accuracy
例如,由于浮点数的精度,下面的代码会产生不希望的结果.
double a = 1 / 3.0;
int b = a * 3; // b will be 0 here
Run Code Online (Sandbox Code Playgroud)
我想知道如果我使用数学函数会出现类似的问题.例如
int a = sqrt(4); // Do I have guarantee that I will always get 2 here?
int b = log2(8); // Do I have guarantee that I will always get 3 here?
Run Code Online (Sandbox Code Playgroud)
如果没有,如何解决这个问题?
编辑:
实际上,当我为算法任务编程时,我遇到了这个问题.在那里,我想得到
最大的整数,是2的幂,小于或等于整数N.
所以圆函数无法解决我的问题.我知道我可以通过循环来解决这个问题,但它似乎不是很优雅.
我想知道是否
int a = pow(2, static_cast<int>(log2(N)));
Run Code Online (Sandbox Code Playgroud)
总能给出正确的结果.例如,如果N == 8,log2(N)有可能给出类似于2.9999999999999的内容,最终结果是4而不是8吗?
我想知道如果我使用数学函数会出现类似的问题.
实际上,log2(8)基本操作(包括*)不存在可能阻止为3 的问题.但它存在于该log2功能中.
你混淆了两个不同的问题:
double a = 1 / 3.0;
int b = a * 3; // b will be 0 here
Run Code Online (Sandbox Code Playgroud)
在上面的例子中,a不完全是1/3,所以有可能a*3不产生1.0.该产品可能碰巧到了1.0,但事实并非如此.但是,如果a不知何故恰好是1/3,那么a3 的乘积就完全正确1.0,因为这就是IEEE 754浮点的工作原理:基本运算的结果是相同运算的数学结果的最接近的可表示值.在同一个操作数上.如果确切的结果可以表示为浮点数,那么表示就是你得到的.
sqrt是"基本操作"的一部分,所以sqrt(4)保证始终,没有例外,在IEEE 754系统,是2.0.
log2不属于基本操作的一部分.IEEE 754标准不保证实现此功能的结果最接近数学结果.它可以是更远的另一个可表示的数字.因此,如果没有关于log2您使用的函数的更多假设,则无法确定log2(8.0)可能的内容.
然而,大多数基本功能的合理质量的实现,例如log2保证实现的结果在数学结果的1 ULP内.当数学结果不可表示时,这意味着上面的可表示值或下面的值(但不一定是两者中最接近的一个).当数学结果完全可以表示时(例如3.0),那么这个表示仍然是唯一保证返回的表示.
所以log2(8),答案是"如果你有一个合理的质量实现log2,你可以期望结果是3.0`".
不幸的是,并非每个基本功能的每个实现都是高质量的实现.请参阅此博客文章,这是由计算时广泛使用的pow超过1 ULP的不准确实现引起的pow(10.0, 2.0),因此返回99.0而不是100.0.
接下来,在每种情况下,将浮点分配给int具有隐式转换的a.此转换在C++标准中定义为截断浮点值(即向零舍入).如果希望浮点计算的结果为整数,则可以在分配浮点值之前将浮点值舍入为最接近的整数.在错误未累积到大于1/2的值的所有情况下,它将有助于获得所需的答案:
int b = std::nearbyint(log2(8.0));
Run Code Online (Sandbox Code Playgroud)
最后简单回答问题的标题:是的,在使用浮点函数产生积分的最终结果时,你应该担心准确性.即使有基本操作的保证,这些功能也不会出现.
| 归档时间: |
|
| 查看次数: |
146 次 |
| 最近记录: |