Die standardmäßige numpy runde tie breaking folgt der IEEE 754 Konvention, um die Hälfte auf die nächste gerade Zahl zu runden. Gibt es eine Möglichkeit, ein anderes Rundungsverhalten anzugeben, z. rund in Richtung Null oder in Richtung -inf? Ich spreche nicht über Decke oder Boden, ich brauche nur andere Krawatte brechen.Tie breaking of round mit numpy
Antwort
NumPy gibt keine Kontrolle über den internen Rundungsmodus. Hier sind zwei Alternativen:
- Verwenden
gmpy2
, wie in this answer skizziert. Dies gibt Ihnen die volle Kontrolle über den Rundungsmodus, abergmpy2
für einfache float-Mathematik ist wahrscheinlich langsamer als NumPy. Verwenden Sie
fesetround
überctypes
, um den Rundungsmodus manuell festzulegen. Dies ist systemspezifisch, da die Konstanten je nach Plattform variieren können. Überprüfen Siefenv.h
für die konstanten Werte auf Ihrer Plattform. Auf meinem Rechner (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
Danke für Ihre Antwort! Der Vollständigkeit halber: Mit linux fand ich fesetround nicht in libc, sondern in libm, also war die Ladezeile 'libm = ctypes.CDLL ('libm.so.6')'. Die Konstanten sind gleich. – Michael
Mit dem Open-Source-Software SWIG
nneonneo Antwort zu vervollständigen, wenn Sie nicht über ein großes Paket wie gmpy2 weder Gebrauch herunterladen möchten Ein systemspezifischer Code mit Ctypes, Sie können eine Bindung von C mit SWIG verwenden (vorausgesetzt, Sie haben es bereits auf Ihrem Computer).
Hier ist, was Sie tun müssen (in vier Stufen):
1) zunächst eine Datei mit dem Namen 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) Dann wird eine Datei 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) In Ihrem Terminal (wenn Sie eine andere Version als python2.7 verwenden, python2.7 in der zweiten Zeile ersetzen):
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) die Bibliothek _rounding.so importieren, die Sie gerade durch Abkleben am Anfang Ihres Python-Datei erstellt:
from your_path_to_rounding.so import rounding
Aus Neugier, wie können diese Tie-Regeln zu brechen in der Praxis relevant werden? Immerhin liegt der Unterschied in der gleichen Größenordnung wie der Quantisierungsfehler. – maxy
Ich rekonstruiere einige komplexe Berechnungen von Matlab in Python. Die Krawatte, die dort bricht, ist anders, also ruiniert es einige Testfälle, wenn ich die Ergebnisse vergleiche. – Michael