在使用 MSVC2013 的 x64 Windows 上,我正在使用 OpenCV 的 cvRound 函数,目的是从 x.5 值中取整。我遇到了一个不一致的地方 cvRound(17.5f) 返回 18(好!),但 cvRound(20.5f) 返回 20 而不是 21 如预期

cvRound 只是这样实现的,所以它似乎是微软在 _mm_cvtsd_si32() 中的不一致。

int  cvRound( double value )
{
    __m128d t = _mm_set_sd( value );
    return _mm_cvtsd_si32(t);
}

任何人都可以建议如何/为什么会这样?

FWIW, cvRound(20.5f + 1e-3f) 返回 21

最佳答案

SSE 指令的舍入行为可通过浮点环境(特别是 MXCSR 寄存器)进行配置。有 several IEEE rounding modes 。默认的舍入模式是舍入到最接近,并列到偶数,因此如果值正好位于两个可表示值的中间,则结果将舍入到最接近的偶数值。

考虑以下演示不同舍入模式的测试程序:

#include <fenv.h>
#include <immintrin.h>
#include <stdio.h>

int main()
{
    printf("Default:        %d\n", _mm_cvtsd_si32(_mm_set_sd(20.5)));
    fesetround(FE_DOWNWARD);
    printf("FE_DOWNWARD:    %d\n", _mm_cvtsd_si32(_mm_set_sd(20.5)));
    fesetround(FE_UPWARD);
    printf("FE_UPWARD:      %d\n", _mm_cvtsd_si32(_mm_set_sd(20.5)));
    fesetround(FE_TONEAREST);
    printf("FE_TONEAREST:   %d\n", _mm_cvtsd_si32(_mm_set_sd(20.5)));
    fesetround(FE_TOWARDZERO);
    printf("FE_TOWARDZERO:  %d\n", _mm_cvtsd_si32(_mm_set_sd(20.5)));
}

输出:
Default:        20
FE_DOWNWARD:    20
FE_UPWARD:      21
FE_TONEAREST:   20
FE_TOWARDZERO:  20

关于c++ - cvRound() 中的 x64 舍入不一致 (_mm_cvtsd_si32),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27989989/

10-12 23:14