相关疑难解决方法(0)

浮点数学是否破碎?

请考虑以下代码:

0.1 + 0.2 == 0.3  ->  false
Run Code Online (Sandbox Code Playgroud)
0.1 + 0.2         ->  0.30000000000000004
Run Code Online (Sandbox Code Playgroud)

为什么会出现这些不准确之处?

language-agnostic math floating-point floating-accuracy

2798
推荐指数
28
解决办法
28万
查看次数

C和C++标准的数学精度要求

难道C和C++标准要求在数学运算math.h上的浮动点(即sqrt,exp,log,sin,...)返回数值最佳的解决方案?

对于给定的(精确且有效的)输入,通常显然不是这些函数的精确浮点输出.但输出是否必须是最接近数学上精确值的可表示值?

如果没有,是否有任何关于精度的要求(可能是平台特定的/在其他标准中?),以便我能够在我的代码中对计算错误进行最坏情况估计?现代实施的数值误差的典型限制是什么?

c c++ floating-point math.h

12
推荐指数
1
解决办法
1048
查看次数

如果两种语言遵循IEEE 754,两种语言的计算会产生相同的答案吗?

我正在将程序从Scilab代码转换为C++.特别是一个循环产生的结果与原始的Scilab代码略有不同(这是一段很长的代码,因此我不会在问题中包含它,但我会尽力总结下面的问题).

问题是,循环的每一步都使用上一步的计算.此外,计算之间的差异仅在第100,000次迭代(大约300,000次)中变得明显.

注意:我正在使用"format(25)"将我的C++程序的输出与Scilab 5.5.2的输出进行比较.命令.含义我正在比较25位有效数字.我还想指出,我理解在一定数量的位之后无法保证精度,但在评论之前阅读下面的部分.到目前为止,两种语言之间的所有计算都相同,最多可达25位.

为了找到问题的根源,到目前为止我已经尝试过:

  1. 检查正在使用的数据类型:

我已经设法确认Scilab正在使用IEEE 754双打(根据语言文档).另外,根据维基百科,C++ 并不需要使用IEEE 754双打,但我可以告诉,我到处使用双C++中它已完全匹配的Scilab的结果.

  1. 检查超越函数的使用:

我还读过每个计算机科学家应该知道的关于浮点运算的内容,IEEE不要求超越函数完全舍入.考虑到这一点,我在两种语言中比较了这些函数的结果(sin(),cos(),exp()),结果看起来是相同的(最多25位).

  1. 使用其他功能和预定义值:

我重复了上述步骤,以便使用sqrt()和pow().以及Pi的值(我在C++中使用M_PI,在Scilab中使用%pi).同样,结果是一样的.

  1. 最后,我重写了循环(非常仔细),以确保两种语言之间的代码相同.

注意:有趣的是,我注意到,对于上述所有计算,两种语言之间的结果与计算的实际结果(浮点运算之外)相匹配得更远.例如:

使用Wolfram Alpha = sin(x)的值= 0.123456789 .....

使用Scilab&C++ = sin(x)的值= 0.12345yyyyy .....

甚至一旦使用Scilab或C++计算的值开始与实际结果不同(来自Wolfram).每种语言的结果仍然相互匹配.这使我相信大多数值都以相同的方式计算(在两种语言之间).即使IEEE 754不要求它们.


我最初的想法是上述前三点之一,两种语言之间的实现方式不同.但据我所知,一切似乎都会产生相同的结果.

是否有可能即使这些循环的所有输入都相同,结果也可能不同?可能是因为一个非常小的错误(过去我能看到的25位数)正在发生,随着时间累积?如果是这样,我该如何解决这个问题呢?

c++ floating-point precision rounding-error scilab

10
推荐指数
2
解决办法
367
查看次数

非常大数字的正弦的标准

我正在TeX中编写一个(几乎)IEEE 854兼容的浮点实现(它只支持32位整数).该标准仅规定的结果+,-,*,/,比较,余数,并且sqrt:对于这些操作,结果应(根据舍入模式)是相同的舍入准确结果的表示的数.

我似乎记得IEEE指定超越函数(sin,exp...)应该产生忠实的结果(在默认的舍入到最近的模式中,它们应该输出围绕确切结果的两个可表示数字之一).计算小数的正弦是相当简单的:移动2*pi的倍数以获得[0,2*pi]范围内的数字,然后再做一些工作以将范围缩小到[0,pi/4] ,并使用泰勒系列.

现在假设我想计算sin(1e300).为此,我需要找到1e300 modulo 2*pi.这需要知道pi的300(316?)个小数,因为只有16个小数,结果没有任何意义(特别是,它不是忠实的).

关于结果sin(1e300)和类似的非常大的数字应该有标准吗?

其他浮点实现有什么作用?

floating-point decimal ieee-754

7
推荐指数
1
解决办法
1996
查看次数

在任何基于x86的体系结构中,是否有浮点密集型代码会产生位精确的结果?

我想知道在C或C ++中使用浮点运算的任何代码在任何基于x86的体系结构中是否都会产生精确的结果,而不管代码的复杂性如何。

据我所知,自从Intel 8087开始,任何x86架构都使用了准备处理IEEE-754浮点数的FPU单元,而且我看不出任何原因导致不同架构的结果不同。但是,如果它们不同(即由于不同的编译器或不同的优化级别),那么是否有某种方法可以通过仅配置编译器来产生位精确结果?

c x86 ieee-754 fast-math

5
推荐指数
1
解决办法
824
查看次数

C- 浮点精度

我有一个程序:

int main() 
{   
        float f = 0.0f;  
        int i;  

        for (i = 0 ; i < 10 ; i++) 
                f = f + 0.1f; 

        if (f == 1.0f) 
                printf("f is 1.0 \n"); 
        else 
                printf("f is NOT 1.0\n"); 

        return 0; 
} 
Run Code Online (Sandbox Code Playgroud)

它总是打印f is NOT 1.0. 我知道这与 C 中的浮点精度有关。但我不确定它到底在哪里搞砸了。有人可以解释一下为什么不打印另一行吗?

c floating-point precision

1
推荐指数
1
解决办法
7831
查看次数

Clang 和 Visual C++ 之间的 acos 精度略有差异

我正在使用一些跨平台代码。在 Mac 上它是用 Clang 编译的,在 Windows 上它是用 Visual C++ 编译的。

有一个计算可能很敏感,并且触发断言的 Mac 和 Windows 之间存在差异。最终 acos 结果之间存在差异,但我不清楚为什么。

在这两个平台上,acos 的输入恰好是 -1.0f。在 Visual C++ 中,acos(-1.0f)为 3.14159274。这就是 pi 作为浮点数的值,这正是我所期望的。

但在 macOS 上:

float value = acos(-1.0f);

...计算结果为 3.1415925。这足以引发代码中的问题。acos 是一种对于 float 来说可能不精确的操作 - 我理解这一点。并且不同的编译器可以有不同的acos实现。我只是不清楚为什么 Clang 似乎对如此简单的 acos 结果有问题,而 Visual C++ 却没有。浮点数能够代表 3.14159274,但这不是我得到的结果。

可以使用以下命令从 Xcode 版本的 Clang 中获取准确/Visual C++ 对齐的值:

float value = (float)acos((double)-1.0f);

因此,我可以通过提高精度来解决这个问题,然后将值向下转换回浮点数以保留与 Windows 相同的舍入。我只是在寻找一个理由,说明当 VC++ 编译器似乎不存在精度问题时,为什么需要额外的精度。Clang/Xcode/VC++ 数学库之间也可能存在差异。我只是假设 acos(-1.0) 可能在编译器中更稳定。我在舍入模式中找不到任何差异(即使舍入不是必需的),并且 Xcode 和 Visual Studio 中的新项目也显示出相同的差异。两台机器都是英特尔的。

c++ math

1
推荐指数
1
解决办法
309
查看次数

双倍和准确

使用long double我得到18/19 = 0.947368421052631578...,并且947368421052631578是重复小数.使用double我得到0.947368421052631526...然而,前者是正确的.为什么这么错误的结果呢?

感谢帮助.

c++ math double

0
推荐指数
3
解决办法
7704
查看次数