Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 当数值变得很小时,为什么这些计算需要20倍以上的时间_C++_C++builder_X86 - Fatal编程技术网

C++ 当数值变得很小时,为什么这些计算需要20倍以上的时间

C++ 当数值变得很小时,为什么这些计算需要20倍以上的时间,c++,c++builder,x86,C++,C++builder,X86,我是电路设计师,不是软件工程师,所以我不知道如何追踪这个问题 我正在使用一些IIR过滤器代码,当我通过过滤器处理非常小的值时,我会遇到执行速度非常慢的问题。为了找到问题,我编写了这个测试代码 通常,循环将在大约200毫秒内运行。(我没有测量它。)但是当选中TestCheckBox->时,它需要大约7秒的时间来运行。问题在于循环中A、B、C和D的大小减小,这正是IIR过滤器中的值在其输入变为零后发生的情况 我相信问题在于变量的指数值小于-308。一个简单的修复方法是将变量声明为long doubl

我是电路设计师,不是软件工程师,所以我不知道如何追踪这个问题

我正在使用一些IIR过滤器代码,当我通过过滤器处理非常小的值时,我会遇到执行速度非常慢的问题。为了找到问题,我编写了这个测试代码

通常,循环将在大约200毫秒内运行。(我没有测量它。)但是当选中TestCheckBox->时,它需要大约7秒的时间来运行。问题在于循环中A、B、C和D的大小减小,这正是IIR过滤器中的值在其输入变为零后发生的情况

我相信问题在于变量的指数值小于-308。一个简单的修复方法是将变量声明为long double,但在实际代码中这不是一个容易的修复方法,而且我似乎不需要这样做

你知道为什么会发生这种情况,以及一个简单的解决方法是什么吗

如果是问题,我使用C++ Builder XE3../P>
int j;
double A, B, C, D, E, F, G, H;
//long double A, B, C, D, E, F, G, H; // a fix
A = (double)random(100000000)/10000000.0 - 5.0;
B = (double)random(100000000)/10000000.0 - 5.0;
C = (double)random(100000000)/10000000.0 - 5.0;
D = (double)random(100000000)/10000000.0 - 5.0;
if(TestCheckBox->Checked)
 {
  A *= 1.0E-300;
  B *= 1.0E-300;
  C *= 1.0E-300;
  D *= 1.0E-300;
 }
for(j=0; j<=1000000; j++)
{
 A *= 0.9999;
 B *= 0.9999;
 C *= 0.9999;
 D *= 0.9999;
 E = A * B + C - D; // some exercise code
 F = A - C * B + D;
 G = A + B + C + D;
 H = A * C - B + G;
 E = A * B + C - D;
 F = A - C * B + D;
 G = A + B + C + D;
 H = A * C - B + G;
 E = A * B + C - D;
 F = A - C * B + D;
 G = A + B + C + D;
 H = A * C - B + G;
}
但是,这些定义不在XE3数学库中,因此我使用了

controlfp(0x01000000, 0x03000000) 
但这对XE3没有影响。维基百科的文章中也没有提到这个代码


有什么建议吗?

您已经进入了浮点下溢的领域,导致了非规范化的数字-这取决于您可能被困在软件中的硬件,这将比硬件操作慢得多

您遇到了非规范数字(小于
DBL_MIN
的数字,其中最高有效位被视为零)。非规范化扩展了可表示浮点数的范围,对于在FP算法中保持某些有用的错误界限很重要,但对它们的操作要比对正常FP数的操作慢得多。它们的精度也较低。因此,您应该尽量使所有数字(中间量和最终量)大于DBL_MIN


为了提高性能,您可以通过调用
\u controlfp(\u DN\u FLUSH,\u MCW\u DN)
(或者根据操作系统和编译器的不同,调用类似的函数)强制将非规范化刷新为零

我在奔腾上运行自己的代码。我不会看到下溢错误。为什么变量不直接归零?@user5108\u Dan下溢异常(以及其他FP异常)通常在默认情况下被屏蔽。它们不会变为零,因为底流可以生成非规范结果,而不仅仅是零。不,这在IEEE算法中会悄无声息地发生,除非您特别注意(或使用特殊编译选项)导致不同的行为。在某些系统上,你可以拦截这些陷阱,但我认为这取决于系统。如果这种情况经常发生,这对性能来说可能是一个真正令人头疼的问题(NANs和其他IEEE功能也是如此),但总体而言,它提高了计算的准确性。对的答案可能会有所帮助。当数字变小时,处理它们的时间不会变长。我的理论是,您开始触发浮点异常(下溢),处理数百万个浮点异常可能确实需要很长时间。不要用1e-300左右的数字计算,它们没有物理意义。普朗克单位的宇宙直径约为1e62。你们真的在使用英特尔奔腾处理器吗?如果不是的话,我认为这个标签是不相关的。有没有一个简单的方法让变量变为零而不是controlfp(0x01000000, 0x03000000)