web-dev-qa-db-ja.com

タイプがfloatのステップの範囲

ドキュメント は基本的に、rangeがこの実装とまったく同じように動作する必要があることを示しています(正のstepの場合):

def range(start, stop, step):
  x = start
  while True:
    if x >= stop: return
    yield x
    x += step

また、引数は整数でなければならないとも述べています。何故ですか?ステップがフロートの場合、その定義も完全に有効ではありませんか?

私の場合、私はespです。 range引数としてfloat型を受け入れるstep関数が必要です。 Pythonにありますか、自分で実装する必要がありますか?


より具体的には、このCコードをPythonにナイスな方法で直接変換するにはどうすればよいですか(つまり、手動でwhile- loopを介して行うだけではありません):

for(float x = 0; x < 10; x += 0.5f) { /* ... */ }
47
Albert

numpy.arange

編集:ドキュメントは numpy.linspace 。 気づいてくれてありがとう@Droogans =)

51
Katriel

1つの説明は、浮動小数点の丸めの問題かもしれません。たとえば、あなたが呼び出すことができる場合

range(0, 0.4, 0.1)

あなたはの出力を期待するかもしれません

[0, 0.1, 0.2, 0.3]

しかし、あなたは実際に次のようなものを得ます

[0, 0.1, 0.2000000001, 0.3000000001]

丸めの問題が原因です。また、範囲は何らかのインデックスの生成によく使用されるため、整数のみです。

それでも、フロート用の範囲ジェネレーターが必要な場合は、独自のものをロールバックできます。

def xfrange(start, stop, step):
    i = 0
    while start + i * step < stop:
        yield start + i * step
        i += 1
35
Zarkonnen

範囲式で小数を使用できるようにするためのクールな方法は、次のとおりです。[x * range for x in range(0、10)]

13
mariana soffer

浮動小数点の問題は、不正確なために、期待した数のアイテムを取得できない可能性があることです。アイテムの正確な数が非常に重要な多項式で遊んでいる場合、これは実際の問題になる可能性があります。

本当に必要なのは算術的進行です。次のコードは、intfloatおよびcomplex ...および文字列、リスト...

def arithmetic_progression(start, step, length):
    for i in xrange(length):
        yield start + i * step

このコードは、現在の合計を維持する他の選択肢よりも、最後の値が期待値の雄牛のwithin音内にある可能性が高いことに注意してください。

>>> 10000 * 0.0001, sum(0.0001 for i in xrange(10000))
(1.0, 0.9999999999999062)
>>> 10000 * (1/3.), sum(1/3. for i in xrange(10000))
(3333.333333333333, 3333.3333333337314)

訂正:ここに 競合するランニングトータルガジェット

def kahan_range(start, stop, step):
    assert step > 0.0
    total = start
    compo = 0.0
    while total < stop:
        yield total
        y = step - compo
        temp = total + y
        compo = (temp - total) - y
        total = temp

>>> list(kahan_range(0, 1, 0.0001))[-1]
0.9999
>>> list(kahan_range(0, 3333.3334, 1/3.))[-1]
3333.333333333333
>>>
6
John Machin

浮動小数点数を一緒に追加すると、しばしば少しのエラーが発生します。 range(0.0, 2.2, 1.1)[0.0, 1.1]または[0.0, 1.1, 2.199999999]を返しますか?厳密な分析なしに確実な方法はありません。

本当に必要な場合は、投稿したコードは回避策です。考えられる欠点に注意してください。

5
Mark Ransom

十分な特殊なケースを次に示します。

 [ (1.0/divStep)*x for x in range(start*divStep, stop*divStep)]

あなたの場合、これは次のようになります:

#for(float x = 0; x < 10; x += 0.5f) { /* ... */ } ==>
start = 0
stop  = 10
divstep = 1/.5 = 2 #This needs to be int, thats why I said 'special case'

など:

>>> [ .5*x for x in range(0*2, 10*2)]
[0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5, 6.0, 6.5, 7.0, 7.5, 8.0, 8.5, 9.0, 9.5]
3
ntg

これは私が使用するものです:

numbers = [float(x)/10 for x in range(10)]

のではなく:

numbers = [x*0.1 for x in range(10)]
that would return :
[0.0, 0.1, 0.2, 0.30000000000000004, 0.4, 0.5, 0.6000000000000001, 0.7000000000000001, 0.8, 0.9]

それが役に立てば幸い。

1
Andrey