当时我正在研究大学的东西,我想知道这两者之间的区别:
double TComplejo::Mod(void) const { double a = sqrt(re * re + im * im); return a; }
还有这个
double TComplejo::Mod(void) const { return sqrt(re * re + im * im); }
re和im都是double s。我被警告说"第二个代码片段可能存在十进制精度问题"。
re
im
double
bxgwgixi1#
这两个代码片段之间没有真正的区别:1.* * 精度方面:**这两个代码段都只处理double(没有转换)。将double表达式存储在变量中,然后将其返回与直接返回在语义上相同。1.* * 性能方面:**由于copy-elision(RVO),生成的汇编代码很可能与现代编译器相同。即使在强制复制省略的C++17之前,大多数编译器也会为这两个代码段生成相同的代码。例如:如您所见,here (Godbolt) GCC(带-O2)为两个代码段生成相同的代码。这篇讨论What exactly is the "as-if" rule?的文章包含了一些更相关的信息,应该可以清楚地说明为什么这两个代码段应该表现相同。
fkvaft9z2#
从纯语义的Angular 来看,这两个代码具有完全相同的效果。模数被计算为双精度数。是否将其临时存储在双精度变量中没有区别。顺便说一下,优化编译器很可能像实现第二个版本一样实现第一个版本,因为它认识到临时存储是无用的。无论如何,从实用的Angular 来看,在FPU寄存器为80位而不是64位的x86/x64平台上可能存在差异。在某些优化模式下,数据保留在这些寄存器中,而不是通过舍入复制回内存。因此,80位计算值可以直接从FPU寄存器用于下一次计算。无论如何,在这种情况下,使用临时变量将强制舍入到64位是不太可能的。无论如何,第二种形式只能更加精确。
2条答案
按热度按时间bxgwgixi1#
这两个代码片段之间没有真正的区别:
1.* * 精度方面:**
这两个代码段都只处理
double
(没有转换)。将
double
表达式存储在变量中,然后将其返回与直接返回在语义上相同。1.* * 性能方面:**
由于copy-elision(RVO),生成的汇编代码很可能与现代编译器相同。即使在强制复制省略的C++17之前,大多数编译器也会为这两个代码段生成相同的代码。
例如:如您所见,here (Godbolt) GCC(带-O2)为两个代码段生成相同的代码。
这篇讨论What exactly is the "as-if" rule?的文章包含了一些更相关的信息,应该可以清楚地说明为什么这两个代码段应该表现相同。
fkvaft9z2#
从纯语义的Angular 来看,这两个代码具有完全相同的效果。模数被计算为双精度数。是否将其临时存储在双精度变量中没有区别。顺便说一下,优化编译器很可能像实现第二个版本一样实现第一个版本,因为它认识到临时存储是无用的。
无论如何,从实用的Angular 来看,在FPU寄存器为80位而不是64位的x86/x64平台上可能存在差异。在某些优化模式下,数据保留在这些寄存器中,而不是通过舍入复制回内存。因此,80位计算值可以直接从FPU寄存器用于下一次计算。
无论如何,在这种情况下,使用临时变量将强制舍入到64位是不太可能的。无论如何,第二种形式只能更加精确。