【问题标题】:Tie breaking of round with numpy用 numpy 打破平局
【发布时间】:2013-04-14 15:11:22
【问题描述】:

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

【问题讨论】:

  • 出于好奇,这些打破平局的规则如何在实践中变得相关?毕竟,差异与量化误差在同一数量级。
  • 我正在 python 中从 matlab 重建一些复杂的计算。那里的平局是不同的,所以当我比较结果时它会破坏一些测试用例。

标签: python numpy scipy rounding


【解决方案1】:

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

  1. 使用gmpy2,如this answer 中所述。这使您可以完全控制舍入模式,但使用 gmpy2 进行简单的浮点运算可能比 NumPy 慢。
  2. 通过ctypes 使用fesetround 手动设置舍入模式。这是系统特定的,因为常量可能因平台而异;检查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
    

【讨论】:

  • 感谢您的回答!为了完整性:使用linux,我发现fesetround不在libc中,而是在libm中,所以加载线是libm = ctypes.CDLL('libm.so.6')。常量是一样的。
【解决方案2】:

使用开源软件 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 

【讨论】:

  • 那条from 行不对:不应该只是import rounding吗?
  • 它对我有用“from your_path_to_rounding.so import rounding”,我不知道如何处理你的,抱歉..
  • 等等——你一定是指from directory import rounding。我以为你包括了文件名。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-04-28
  • 1970-01-01
  • 1970-01-01
  • 2013-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多