复数指数运算用size_t出错转double正常,是GCC编译器bug吗
问题原因分析
这不是GCC 7.3.1的编译器bug,是无符号整型和有符号整型混合运算的隐式转换陷阱,核心原因是运算顺序和通常算术转换规则共同作用的结果:
- 首先你的循环变量
m是size_t类型,属于无符号整型。-1 * m * theta * iCpx的运算优先级和结合性是从左到右依次计算,第一步先执行-1 * m,这一步的两个操作数都是整型,还未接触到浮点类型的theta,因此不会触发到double的提升。 - 根据C++的通常算术转换规则,当有符号整型和无符号整型同级别运算时,有符号值会被隐式转换为无符号类型。因此
-1会先被转成size_t类型的最大值(比如64位环境下为2^64 - 1),这一步的运算结果本身就已经完全不符合你预期的-m的语义。 - 后续这个超大的无符号数再和
theta(double类型)运算时才会转成浮点类型,此时你实际传入exp的参数是一个远大于预期的数值,对2π取模后结果固定,所以所有m的输出都是同一个错误值。
编译器无警告的原因
-Wall -Wextra -pedantic-errors默认不开启有符号/无符号混合运算的转换警告,要触发这类警告你需要额外添加编译参数-Wsign-conversion。C++标准本身允许这种隐式转换,因此不属于语法错误,默认的编译检查参数不会报错。
修复方案
可以任选一种:
- 把循环变量
m的类型从size_t改为int,避免无符号转换问题 - 调整运算顺序,让
m先和浮点类型运算:exp(m * theta * iCpx * -1),此时m第一步就会被提升为double,不会触发无符号转换 - 显式把
m转为double:exp(-1 * (double)m * theta * iCpx)
内容的提问来源于stack exchange,提问作者stix
相关产品推荐
相关产品推荐

