Skip to content Skip to sidebar Skip to footer

Tie Breaking Of Round With Numpy

Standard numpy round tie breaking is following IEEE 754 convention, to round half towards the nearest even number. Is there a way to specify different rounding behavior, e.g. round

Solution 1:

NumPy doesn't give any control over the internal rounding mode. Here's two alternatives:

  1. Use gmpy2, as outlined in this answer. This gives you full control over the rounding mode, but using gmpy2 for simple float math is likely to be slower than NumPy.
  2. Use fesetround via ctypes to manually set the rounding mode. This is system-specific because the constants may vary by platform; check fenv.h for the constant values on your platform. On my machine (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)
    printrepr(np.float32(1+v) - np.float32(v/2)) # prints 1.0
    libc.fesetround(FE_UPWARD)
    printrepr(np.float32(1+v) - np.float32(v/2)) # prints 1.0000002

Solution 2:

With the open-source software SWIG

To complete nneonneo answer, if you don't want to download a big package like gmpy2 neither use a system-specific code with ctypes, you can use a binding from C with SWIG (assuming that you already have it on your computer).

Here is what you need to do (in four steps):

1) Write first a file named rounding.i :

%module rounding
%{
/* Put header files here or function declarations like below */voidrnd_arr();
 voidrnd_zero();
 voidrnd_plinf();
 voidrnd_moinf();
 voidrnd_switch();
%}

externvoidrnd_arr();
externvoidrnd_zero();
externvoidrnd_plinf();
externvoidrnd_moinf();
externvoidrnd_switch();

2) Then, a file rnd_C.cpp

#include<stdio.h>#include<stdlib.h>#include<fenv.h>voidrnd_arr(){
  fesetround(FE_TONEAREST);
}


voidrnd_zero(){
  fesetround(FE_TOWARDZERO);
}

voidrnd_plinf(){
  fesetround(FE_UPWARD);
}

voidrnd_moinf(){
  fesetround(FE_DOWNWARD);
}

voidrnd_switch(){
  int r=fegetround();

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

3) In your terminal (if you use another version than python2.7, replace python2.7 at the second line ):

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) import the library _rounding.so that you just created by taping at the beginning of your python file :

from your_path_to_rounding.soimport rounding 

Post a Comment for "Tie Breaking Of Round With Numpy"