10

标准的 numpy 圆形平局打破遵循 IEEE 754 约定,将一半舍入到最接近的偶数。有没有办法指定不同的舍入行为,例如朝零舍入或朝-inf 舍入?我不是在谈论天花板或地板,我只是需要不同的平局。

4

2 回答 2

11

NumPy 不对内部舍入模式进行任何控制。这里有两种选择:

  1. 使用gmpy2,如本答案中所述。这使您可以完全控制舍入模式,但使用gmpy2简单的浮点数学可能比 NumPy 慢。
  2. 使用fesetroundviactypes手动设置舍入模式。这是特定于系统的,因为常量可能因平台而异;检查fenv.h平台上的常量值。在我的机器上(Mac OS X):

    import numpy as np
    import ctypes
    FE_TONEAREST = 0x0000
    FE_DOWNWARD = 0x0400
    FE_UPWARD = 0x0800
    FE_TOWARDZERO = 0x0c00
    libc = ctypes.CDLL('libc.dylib')
    
    v = 1. / (1<<23)
    print repr(np.float32(1+v) - np.float32(v/2)) # prints 1.0
    libc.fesetround(FE_UPWARD)
    print repr(np.float32(1+v) - np.float32(v/2)) # prints 1.0000002
    
于 2013-04-14T15:35:43.960 回答
0

使用开源软件 SWIG

要完成 nneonneo 的回答,如果您不想下载像 gmpy2 这样的大包,也不想使用带有 ctypes 的系统特定代码,您可以使用 C 与 SWIG 的绑定(假设您的计算机上已经有它)。

这是您需要做的(分四个步骤):

1)首先编写一个名为 rounding.i 的文件:

%module rounding
%{
/* Put header files here or function declarations like below */

 void rnd_arr();
 void rnd_zero();
 void rnd_plinf();
 void rnd_moinf();
 void rnd_switch();
%}

extern  void rnd_arr();
extern  void rnd_zero();
extern  void rnd_plinf();
extern  void rnd_moinf();
extern  void rnd_switch();

2) 然后,一个文件 rnd_C.cpp

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


void rnd_arr()
{
  fesetround(FE_TONEAREST);
}


void rnd_zero()
{
  fesetround(FE_TOWARDZERO);
}

void rnd_plinf()
{
  fesetround(FE_UPWARD);
}

void rnd_moinf()
{
  fesetround(FE_DOWNWARD);
}

void rnd_switch()
{
  int r=fegetround();

  if (r==FE_UPWARD)
    r=FE_DOWNWARD;
  else 
    if (r==FE_DOWNWARD)
      r=FE_UPWARD;
    else fprintf(stderr,"ERROR ROUDING MODE \n");
  fesetround(r);
}

3)在您的终端中(如果您使用的不是python2.7版本,请在第二行替换python2.7):

swig -c++ -python -o rounding_wrap.cpp rounding.i
g++ -fPIC -c rounding_wrap.cpp rnd_C.cpp -I/usr/include/python2.7
g++ -shared rounding_wrap.o rnd_C.o -o _rounding.so

4)导入库 _rounding.so 你刚刚通过在你的 python 文件的开头录音创建:

from your_path_to_rounding.so import rounding 
于 2016-07-28T12:55:12.420 回答