cvRound() 中的 x64 舍入不一致 (_mm_cvtsd_si32)
x64 rounding inconsistency in cvRound() (_mm_cvtsd_si32)
在使用MSVC2013的x64 Windows上,我正在使用OpenCV的cvRound
函数,目的是从x.5
值中舍入。我遇到了不一致的情况,cvRound(17.5f)
返回18
(好!),但cvRound(20.5f)
返回20
而不是按预期21
cvRound是这样简单地实现的,所以它似乎是_mm_cvtsd_si32()
Microsoft不一致。
int cvRound( double value )
{
__m128d t = _mm_set_sd( value );
return _mm_cvtsd_si32(t);
}
谁能建议如何/为什么会这样?
FWIW,cvRound(20.5f + 1e-3f)
返回21
.
小的半整数可以用二进制浮点数精确表示——0.5 是 2 的幂。
真正发生的事情是"四舍五入到偶数"。 这是一种消除半整数总是向上舍入时发生的偏差的方法。
http://en.wikipedia.org/wiki/Rounding#Round_half_to_even
SSE 指令的舍入行为可通过浮点环境(特别是 MXCSR 寄存器)进行配置。 有几种 IEEE 舍入模式。 默认舍入模式是舍入到最近值、并列到偶数,因此,如果该值正好位于两个可表示值的中间,则结果将舍入到最接近的偶数值。
请考虑以下测试程序,该程序演示了不同的舍入模式:
#include <fenv.h>
#include <immintrin.h>
#include <stdio.h>
int main()
{
printf("Default: %dn", _mm_cvtsd_si32(_mm_set_sd(20.5)));
fesetround(FE_DOWNWARD);
printf("FE_DOWNWARD: %dn", _mm_cvtsd_si32(_mm_set_sd(20.5)));
fesetround(FE_UPWARD);
printf("FE_UPWARD: %dn", _mm_cvtsd_si32(_mm_set_sd(20.5)));
fesetround(FE_TONEAREST);
printf("FE_TONEAREST: %dn", _mm_cvtsd_si32(_mm_set_sd(20.5)));
fesetround(FE_TOWARDZERO);
printf("FE_TOWARDZERO: %dn", _mm_cvtsd_si32(_mm_set_sd(20.5)));
}
输出:
Default: 20
FE_DOWNWARD: 20
FE_UPWARD: 21
FE_TONEAREST: 20
FE_TOWARDZERO: 20
舍
入的工作方式与此代码打印的值相等的原因相同(使用 MSVC2012 进行测试)
float f1 = 20.4999999f;
float f2 = 20.5f;
if(f1==f2)
printf("equaln");
http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
相关文章:
- 如何在C++中将 chrono::秒转换为 HH:MM:SS 格式的字符串?
- 如何从远程 SFTP 服务器获取 HH-MM-SS 时间戳格式的文件列表
- 将 hh:mm:ss.zzz 时间 QString 转换为毫秒的单行函数?
- 格式化时间 c++ dd/mm/yyyy hh:ss.
- 如何将鼠标坐标转换为"mm"
- 如何在C++中将秒更改为 HH:MM:SS 格式?
- 将源文件扩展名从 .m 更改为 .mm 在屏幕保护程序项目的 Xcode 9.3 中失败
- -MM 标志在 g++ 中有什么作用
- 如何以"hh:mm:ss"格式读取C ++中的HH,MM和SS
- 从用户那里获取"yyyy/mm/dd, hh:mm"形式的日期输入并验证C++中的日期?
- 在 C++11 中表示日内时间 HH:MM:SS 的最佳方法是什么?
- 从 ObjC 代码调用 .mm 类方法时编译错误
- C - 用STD :: difftime编写调度程序 - 如何在白天检查时间(HH:MM:SS)
- 如何在 Xcode Objective-C Project 中的 .mm 类扩展中导入/使用 swift 静态库/框架
- C++ 用户输入的字符串必须采用 DD-MM-YYYY 格式
- 以 hh:mm 格式添加时间,C++
- cygwin上的gcc -MM:有时是Unix风格的路径
- 从工作iOS项目中导入.cpp文件并将其重命名为.mm问题
- 正在尝试将time_t数据类型转换为(dd/mm/yyyy)格式C++
- 为什么 g++ -MM 选项忽略当前工作目录的包含文件