2013-07-03 10 views
5

GNU Cライブラリの機能はdrem(別名remainder)です。Google App Engine Python 2.7ランタイムで、GNU Cライブラリのdrem/remainder関数をシミュレートする方法はありますか?

Google App Engine Python 2.7ランタイムでサポートされているmodulesを使用してこの機能をシミュレートするにはどうすればよいですか? dremためGNU manualから

これらの機能は、それらが整数に最も近い整数に代えてゼロに向かって内部商nを丸めることを除いfmodようです。たとえば、drem(6.5,2.3)は-0.4を返します。これは6.5から6.9です。 fmodためGNU manualから

これらの機能は、分母によって分子の除算の剰余を計算します。具体的には、戻り値はnumerator-n *分母であり、nは分子を分母で割った商であり、ゼロに向かって整数に丸められます。したがって、fmod(6.5,2.3)は1.9を返し、6.5から4.6を引いた値になります。

def drem(x, y): 
    n = round(x/y) 
    return x - n * y 

しかしパイソン、drem(1.0, 2.0) == -1.0で及びC drem(1.0, 2.0) == 1.0と次のPythonコードが動作するはずドキュメントを読ん

。 Pythonはを返します。とCはを返します。。これはほぼ確実に丸め浮動小数点の内部的な違いです。限り、私は両方の機能は、パラメータ2 * x != yどこに同じことを行うことができます。

私のPython dremの機能は、C言語のものと同じにすることができますか?

+0

Google App Engineで利用できる[サポートされているPythonモジュール](https://developers.google.com/appengine/kb/libraries)のみを使用できることを付け加えておきます。 – Dan

+0

'round()'の代わりに 'numpy.round()'が私の例ではうまくいくようですが、これにエッジケースがあるかどうかを知っていただければ幸いです。 – Dan

+0

私は**ラピッと**そのラウンド関数のためだけに依存していないので、質問はまだ立っています。 – Dan

答えて

5

この問題を解決する鍵は、drem/remainderfunction specificationも半分に円形の内部丸め計算が必要であることを実現することです。

round関数は、Python 2.xでは0から切り離されているので、組み込み関数を使用することはできません。しかし、Python 3.xのround関数は半減するように変更されています。したがって、次のPython 3。XコードはGNU Cライブラリdrem機能と同等になりますが、は、Python 2.xでを動作しません。

def drem(x, y): 
    n = round(x/y) 
    return x - n * y 

我々はdecimalモジュールを使用することができるのPython 2.xとそのremainder_near機能と同じことを達成するために:

import decimal 

def drem(x, y): 
    xd = decimal.Decimal(x) 
    yd = decimal.Decimal(y) 

    return float(xd.remainder_near(yd)) 
1

EDIT:最初のコメントを読んで、​​モジュールを使用できないことを確認しました。とにかく、あなたの問題に対する答えを見つけようとすることで、今日はたくさんのことを学びました。

numpy.round()は、小数点以下を切り捨てて小数点以下を切り捨てることを考えると、numpyを使用するのは良い解決策ではありません。

また、dremは内部でこれをMONSTER functionと呼びます。これはPythonで実装するのが難しいはずです。

this articleに触発されて、drem関数を数学ライブラリから直接呼び出すことをおすすめします。これらの線に沿って何かがトリックを行う必要があります。

from ctypes import CDLL 
# Use the C math library directly from Python 
# This works for Linux, but the version might differ for some systems 
libm = CDLL('libm.so.6') 

# For Windows, try this instead: 
# from ctypes import cdll 
# libm = cdll.libc 

# Make sure the return value is handled as double instead of the default int 
libm.drem.restype = c_double 
# Make sure the arguments are double by putting them inside c_double() 
# Call your function and have fun! 
print libm.drem(c_double(1.0), c_double(2.0)) 
+0

調査に感謝し、「numpy.round」が実行可能でないことを知らせてくれてありがとう。私はdrem内部機能がモンスターであり、それを移植しようとしないことにも同意します! App Engineランタイムモジュールのみを使用するように質問を更新しました。 App Engineランタイムの制限は、私が質問を書いた後、あなたがctypesを使って上記で示唆したことを正確に行うことを試みた後にのみ私に起こりました。 – Dan

関連する問題