Làm thế nào để sử dụng giá trị bước thập phân ()?


744

Có cách nào để bước giữa 0 và 1 bằng 0,1 không?

Tôi nghĩ rằng tôi có thể làm điều đó như sau, nhưng nó đã thất bại:

for i in range(0, 1, 0.1):
    print i

Thay vào đó, nó nói rằng đối số bước không thể bằng 0, điều mà tôi không mong đợi.


17
int (0.1) == 0, vì vậy bước thực sự bằng không. Nó có thể là bất ngờ, nhưng nó bằng không. Bạn có thể muốn giới thiệu lại câu hỏi của mình để phản ánh thực tế rằng đó là điều bạn không mong đợi. Nói "không phải" là sai và sai.
S.Lott

3
BTW Một lớp lót ngắn có thể được cuộn lên bằng cách sử dụng itertools.takewhileitertools.count. drangeMặc dù vậy, nó không tốt hơn hiệu suất.
Kos

1
Thật xấu hổ khi phạm vi của python không cho phép điều này, cho dù việc triển khai một trình tạo thực hiện việc này dễ dàng như thế nào ngay cả khi không tích lũy các lỗi làm tròn. Heck, thậm chí seqcông cụ trong GNU coreutils cho phép một người làm seq 0 0.1 1mà không làm tròn lỗi!
josch

3
@josch: seqsử dụng long doubleloại C trong nội bộ và thể bị lỗi làm tròn. Ví dụ trên máy của tôi, seq 0 0.1 1đưa ra 1là đầu ra cuối cùng của nó (như mong đợi), nhưng seq 1 0.1 2đưa ra 1.9là đầu ra cuối cùng (chứ không phải là dự kiến 2).
Đánh dấu Dickinson

Để thuận tiện, đề xuất của @ Kos có thể được triển khai dưới dạng itertools.takewhile(lambda x: (x+0.05)<1, itertools.count(0,0.1))hoặc itertools.islice(itertools.count(0,0.1), 10)(sau khi bạn có import itertools), mặc dù tôi chưa thử nghiệm hiệu quả hơn
Ẩn danh

Câu trả lời:


906

Thay vì sử dụng một bước thập phân trực tiếp, sẽ an toàn hơn nhiều khi thể hiện điều này theo số lượng điểm bạn muốn. Nếu không, lỗi làm tròn dấu phẩy động có thể cho kết quả sai.

Bạn có thể sử dụng hàm linspace từ thư viện NumPy (không phải là một phần của thư viện chuẩn nhưng tương đối dễ lấy). linspacemất một số điểm để trả về và cũng cho phép bạn chỉ định có bao gồm điểm cuối đúng hay không:

>>> np.linspace(0,1,11)
array([ 0. ,  0.1,  0.2,  0.3,  0.4,  0.5,  0.6,  0.7,  0.8,  0.9,  1. ])
>>> np.linspace(0,1,10,endpoint=False)
array([ 0. ,  0.1,  0.2,  0.3,  0.4,  0.5,  0.6,  0.7,  0.8,  0.9])

Nếu bạn thực sự muốn sử dụng giá trị bước dấu phẩy động, bạn có thể, với numpy.arange.

>>> import numpy as np
>>> np.arange(0.0, 1.0, 0.1)
array([ 0. ,  0.1,  0.2,  0.3,  0.4,  0.5,  0.6,  0.7,  0.8,  0.9])

Lỗi làm tròn điểm nổi sẽ gây ra vấn đề. Đây là một trường hợp đơn giản trong đó lỗi làm tròn gây arangera một mảng có độ dài 4 khi nó chỉ tạo ra 3 số:

>>> numpy.arange(1, 1.3, 0.1)
array([1. , 1.1, 1.2, 1.3])

51
numpy là một thành phần phổ biến của trăn đến nỗi tôi coi câu trả lời này là 'pythonic' nhất trong tất cả.
không kích

21
@AndreTerra Vấn đề là @ numpy @ là gói của bên thứ ba và thêm rất nhiều chi phí về quản lý phụ thuộc, lưu trữ (đối với chính gói đó), v.v. Tùy thuộc vào những gì nhà phát triển đang làm, có thể không thể sử dụng nó
rbaleksandar

Xin lỗi, nhưng tôi đã không hiểu lỗi làm tròn dấu phẩy động trong phần cuối kể từ đó np.linspace(1.,1.3,4)np.arange(1.,1.3,0.1)đưa ra chính xác cùng một đầu ra
mã chết

4
@deadcode Lý do là np.arange được xác định để tạo ra một phạm vi [start,stop)(tức là loại trừ stop), vì vậy người ta sẽ không mong đợi 1.3 được đưa vào danh sách. Xem câu hỏi này để biết tại sao nó vẫn được bao gồm và phải làm gì để chống lại nó.
dennis

5
Bao nhiêu một gói được sử dụng được cho là không có bất kỳ chỉ số nào cho dù đó là "Pythonic."
Hội trường Alex

213

Phạm vi của Python () chỉ có thể thực hiện các số nguyên, không phải dấu phẩy động. Trong trường hợp cụ thể của bạn, bạn có thể sử dụng một sự hiểu biết danh sách thay thế:

[x * 0.1 for x in range(0, 10)]

(Thay thế cuộc gọi đến phạm vi bằng biểu thức đó.)

Đối với trường hợp tổng quát hơn, bạn có thể muốn viết một hàm tùy chỉnh hoặc trình tạo.


36
Thậm chí tốt hơn, bạn chỉ có thể sử dụng trình hiểu trình tạo nếu bạn đang làm việc với Python 2.4+. (x * 0.1 for x in range(0, 10)).
JAB

42
Thậm chí tốt hơn, đặt x/10thay vì x * 0.1: D Thực sự không có gì đặc biệt, nhưng một số con số trong đó sẽ chính xác hơn, ví dụ như 3*0.1bạn nhận được 0.30000000000000004, trong khi cho 3/10 bạn nhận được 0.3:)
Bloke

4
3/10 cho tôi 0, không phải 0,3. 3 / 10.0 cho 0,29999999999999999. Con trăn 2.6.

19
@LarsWirzenius: trong Python 2.2+, from __future__ import division; 3/10trả về 0,3. Hành vi này là mặc định trong Python 3.x.
Benjamin Hodgson

2
Hàm tròn cũng có thể được sử dụng lst = [tròn (x * 0.10,2) cho x trong khoảng (0,10)]
MARK

148

Dựa trên 'xrange ([bắt đầu], dừng [, bước])' , bạn có thể xác định trình tạo chấp nhận và tạo bất kỳ loại nào bạn chọn (bám vào các loại hỗ trợ +<):

>>> def drange(start, stop, step):
...     r = start
...     while r < stop:
...         yield r
...         r += step
...         
>>> i0=drange(0.0, 1.0, 0.1)
>>> ["%g" % x for x in i0]
['0', '0.1', '0.2', '0.3', '0.4', '0.5', '0.6', '0.7', '0.8', '0.9', '1']
>>> 

45
Điều này có vấn đề vòng. Vui lòng xem tại đây: code.activestate.com/recipes/66472
Christian

Tôi sẽ mở rộng nó một chút cho hướng khác với một (trong khi r> dừng) và một bước r - = tương ứng để đưa ra hướng ngược lại.
dùng318904

1
Tôi đã thực hiện một chức năng xfrange mà không có vấn đề chính xác float được đề cập ở trên. Hãy xem thử;) stackoverflow.com/questions/477486/
Carlos Vega

1
Bạn đang tích lũy lỗi làm tròn số. Vui lòng sử dụng thay thế: `i = 0; r = bắt đầu trong khi r <stop: i + = 1; r = bắt đầu + i * bước; năng suất r`
Cees Timmerman

1
Đây là từ pythoncentral.io/pythons-range-feft-explained (và các nguồn tài liệu Python khác)
Apostolos

31

Tăng cường độ icho vòng lặp và sau đó giảm nó khi bạn cần.

for i * 100 in range(0, 100, 10):
    print i / 100.0

EDIT: Thành thật tôi không thể nhớ tại sao tôi nghĩ rằng nó sẽ hoạt động tổng hợp

for i in range(0, 11, 1):
    print i / 10.0

Điều đó nên có đầu ra mong muốn.


Tôi nghĩ rằng bạn sẽ thấy rằng phạm vi () hoạt động với các số nguyên, trong trường hợp này đây sẽ là giải pháp duy nhất, sử dụng cùng chức năng ít nhất.
Matthew Scharley

1
@cmsjr creative: D Chỉ một điều nhỏ: chia cho 100.0 để ngăn Python cắt bớt kết quả nếu bạn đang sử dụng Python 2.x. Tôi nghĩ trong 3.0, nó sẽ hoạt động như bạn đã mã hóa nó.
Dana

2
for i * 100 in range(0, 100, 10): SyntaxError: không thể chỉ định cho nhà điều hành
Anne van Rossum

25

scipycó một hàm dựng sẵn arangeđể khái quát hàm tạo của Python range()để đáp ứng yêu cầu xử lý float của bạn.

from scipy import arange


8
Đây thực sự là chính xác giống như arangebạn có thể tìm thấy trong numpy: >>> import scipy >>> import numpy >>> numpy.arange is scipy.arangesẽ trở lại True.
iFreilicht

from nump import arange as range
shrewmouse

24

NumPy là một chút quá mức, tôi nghĩ vậy.

[p/10 for p in range(0, 10)]
[0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]

Nói chung, để làm một bước-by- 1/xđến ybạn sẽ làm gì

x=100
y=2
[p/x for p in range(0, int(x*y))]
[0.0, 0.01, 0.02, 0.03, ..., 1.97, 1.98, 1.99]

( 1/xtạo ra tiếng ồn làm tròn ít hơn khi tôi kiểm tra).


18

Tương tự như hàm R, seq hàm này trả về một chuỗi theo bất kỳ thứ tự nào được đưa ra giá trị bước chính xác. Giá trị cuối cùng bằng giá trị dừng.

def seq(start, stop, step=1):
    n = int(round((stop - start)/float(step)))
    if n > 1:
        return([start + step*i for i in range(n+1)])
    elif n == 1:
        return([start])
    else:
        return([])

Các kết quả

seq(1, 5, 0.5)

[1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0]

seq(10, 0, -1)

[10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

seq(10, 0, -2)

[10, 8, 6, 4, 2, 0]

seq(1, 1)

[1]


2
Đây là một câu trả lời tuyệt vời cho những người muốn có được nó mà không cần quá nhiều vào con trăn.
Chani

1
Đó gần như là những gì tôi đang tìm kiếm - lưu ý rằng seq(0.5, 3.0)trả lại [0.5, 1.5, 2.5, 3.5]. Để tránh các mục cuối cùng nằm ngoài phạm vi, thay thế n = int(round(...bằng n = int(floor(...dòng from math import floorở trên cùng (ở trên def seq(...).
FriendFX

2
@FriendFX Đừng làm điều này! Nếu floorđược sử dụng, seq(0.2, 0.9, 0.1)sẽ không đạt được điểm cuối bên phải và sẽ quay lại[0.2, 0.30000000000000004, 0.4, 0.5, 0.6000000000000001, 0.7, 0.8]
fdermishin

@ user502144: Bắt tốt, cảm ơn. Tôi đoán tôi phải giải quyết một trong những giải pháp phức tạp hơn để giữ cho nó chung chung.
FriendFX

14

Hàm tích hợp phạm vi () trả về một chuỗi các giá trị nguyên, tôi sợ, vì vậy bạn không thể sử dụng nó để thực hiện bước thập phân.

Tôi muốn nói chỉ cần sử dụng một vòng lặp while:

i = 0.0
while i <= 1.0:
    print i
    i += 0.1

Nếu bạn tò mò, Python đang chuyển đổi 0,1 thành 0 của bạn, đó là lý do tại sao nó cho bạn biết đối số không thể bằng không.


2
Đừng làm điều này! Thêm .110 lần không giống như thêm 1! docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
mèo

12

Đây là một giải pháp sử dụng itertools :

import itertools

def seq(start, end, step):
    if step == 0:
        raise ValueError("step must not be 0")
    sample_count = int(abs(end - start) / step)
    return itertools.islice(itertools.count(start, step), sample_count)

Ví dụ sử dụng:

for i in seq(0, 1, 0.1):
    print(i)

Để hoàn thiện, bạn nên tính giá trị tuyệt đối cho biến sample_count, theo cách đó, hàm của bạn cũng sẽ hoạt động cho một khởi đầu âm (tức là từ -10 đến 10)
Deleteman 18/03/2015

10
[x * 0.1 for x in range(0, 10)] 

trong Python 2.7x cung cấp cho bạn kết quả của:

[0,0, 0,1, 0,2, 0,30000000000000004, 0,4, 0,5, 0,6000000000000001, 0,7000000000000001, 0,8, 0,9]

nhưng nếu bạn sử dụng:

[ round(x * 0.1, 1) for x in range(0, 10)]

cung cấp cho bạn mong muốn:

[0,0, 0,1, 0,2, 0,3, 0,4, 0,5, 0,6, 0,7, 0,8, 0,9]



5

Và nếu bạn làm điều này thường xuyên, bạn có thể muốn lưu danh sách đã tạo r

r=map(lambda x: x/10.0,range(0,10))
for i in r:
    print i

5

more_itertoolslà thư viện của bên thứ ba thực hiện một numeric_rangecông cụ:

import more_itertools as mit


for x in mit.numeric_range(0, 1, 0.1):
    print("{:.1f}".format(x))

Đầu ra

0.0
0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.8
0.9

Công cụ này cũng hoạt động cho DecimalFraction.


4

Các phiên bản của tôi sử dụng chức năng phạm vi ban đầu để tạo các chỉ số nhân cho ca. Điều này cho phép cùng một cú pháp cho chức năng phạm vi ban đầu. Tôi đã thực hiện hai phiên bản, một phiên bản sử dụng float và một phiên bản sử dụng Decimal, vì tôi thấy rằng trong một số trường hợp, tôi muốn tránh sự trôi dạt vòng tròn được giới thiệu bởi số học dấu phẩy động.

Nó phù hợp với kết quả tập hợp trống như trong phạm vi / xrange.

Chỉ truyền một giá trị số duy nhất cho một trong hai hàm sẽ trả lại đầu ra phạm vi tiêu chuẩn cho giá trị trần số nguyên của tham số đầu vào (vì vậy nếu bạn cho nó 5.5, nó sẽ trả về phạm vi (6).)

Chỉnh sửa: mã bên dưới hiện có sẵn dưới dạng gói trên pypi: Franges

## frange.py
from math import ceil
# find best range function available to version (2.7.x / 3.x.x)
try:
    _xrange = xrange
except NameError:
    _xrange = range

def frange(start, stop = None, step = 1):
    """frange generates a set of floating point values over the 
    range [start, stop) with step size step

    frange([start,] stop [, step ])"""

    if stop is None:
        for x in _xrange(int(ceil(start))):
            yield x
    else:
        # create a generator expression for the index values
        indices = (i for i in _xrange(0, int((stop-start)/step)))  
        # yield results
        for i in indices:
            yield start + step*i

## drange.py
import decimal
from math import ceil
# find best range function available to version (2.7.x / 3.x.x)
try:
    _xrange = xrange
except NameError:
    _xrange = range

def drange(start, stop = None, step = 1, precision = None):
    """drange generates a set of Decimal values over the
    range [start, stop) with step size step

    drange([start,] stop, [step [,precision]])"""

    if stop is None:
        for x in _xrange(int(ceil(start))):
            yield x
    else:
        # find precision
        if precision is not None:
            decimal.getcontext().prec = precision
        # convert values to decimals
        start = decimal.Decimal(start)
        stop = decimal.Decimal(stop)
        step = decimal.Decimal(step)
        # create a generator expression for the index values
        indices = (
            i for i in _xrange(
                0, 
                ((stop-start)/step).to_integral_value()
            )
        )  
        # yield results
        for i in indices:
            yield float(start + step*i)

## testranges.py
import frange
import drange
list(frange.frange(0, 2, 0.5)) # [0.0, 0.5, 1.0, 1.5]
list(drange.drange(0, 2, 0.5, precision = 6)) # [0.0, 0.5, 1.0, 1.5]
list(frange.frange(3)) # [0, 1, 2]
list(frange.frange(3.5)) # [0, 1, 2, 3]
list(frange.frange(0,10, -1)) # []

Làm thế nào có thể frangelàm việc nếu dừng là None? Đó là một phần của mã thậm chí không xem xét kích thước bước nữa.
josch

1
@josch rangecó hai chữ ký : range(stop), giả sử mặc định start=0, step=1range(start, stop, step)không có giả định nào được đưa ra. frangephản ánh điều đó. Khi sử dụng range(stop)chữ ký, cả hai frangedrangebắt đầu từ 0 và tăng 1, vì vậy hành vi của chúng giống hệt với range(stop)hành vi thông thường với điểm dừng được làm tròn đến số nguyên gần nhất.
Nisan.H

4

Đây là giải pháp của tôi để có được phạm vi với các bước nổi.
Sử dụng chức năng này không cần thiết phải nhập numpy, cũng không cài đặt nó.
Tôi khá chắc chắn rằng nó có thể được cải thiện và tối ưu hóa. Hãy làm điều đó và gửi nó ở đây.

from __future__ import division
from math import log

def xfrange(start, stop, step):

    old_start = start #backup this value

    digits = int(round(log(10000, 10)))+1 #get number of digits
    magnitude = 10**digits
    stop = int(magnitude * stop) #convert from 
    step = int(magnitude * step) #0.1 to 10 (e.g.)

    if start == 0:
        start = 10**(digits-1)
    else:
        start = 10**(digits)*start

    data = []   #create array

    #calc number of iterations
    end_loop = int((stop-start)//step)
    if old_start == 0:
        end_loop += 1

    acc = start

    for i in xrange(0, end_loop):
        data.append(acc/magnitude)
        acc += step

    return data

print xfrange(1, 2.1, 0.1)
print xfrange(0, 1.1, 0.1)
print xfrange(-1, 0.1, 0.1)

Đầu ra là:

[1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0]
[0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1]
[-1.0, -0.9, -0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1, 0.0]

1
Có lỗi khi thiếu giá trị cuối cùng nếu nó nằm trong 1 bước của giá trị dừng. tức là xfrange (1,10,2) chỉ thực hiện 1,3,5,7, thiếu 9
Lobe

Để tham khảo và các độc giả khác, vui lòng so sánh việc triển khai này với stackoverflow.com/a/477610/54964 . Điều này dường như không có vấn đề nổi lớn.
Léo Léopold Hertz

@carlosvega Bạn có thể xác nhận tại sao Lobe nhận được kết quả của mình không?
Léo Léopold Hertz

3

Để hoàn thiện cửa hàng, một giải pháp chức năng:

def frange(a,b,s):
  return [] if s > 0 and a > b or s < 0 and a < b or s==0 else [a]+frange(a+s,b,s)

2

Bạn có thể sử dụng chức năng này:

def frange(start,end,step):
    return map(lambda x: x*step, range(int(start*1./step),int(end*1./step)))

Dường như không hoạt động chính xác, ví dụ list(frange(99.8, 100.1, 0.1)) => [99.7, 99.80000000000001, 99.9]
Shai Coleman

2

Bí quyết để tránh vòng-off vấn đề là sử dụng một số riêng biệt để di chuyển qua dãy núi này, mà bắt đầu và một nửa các bước trước sự khởi đầu .

# floating point range
def frange(a, b, stp=1.0):
  i = a+stp/2.0
  while i<b:
    yield a
    a += stp
    i += stp

Ngoài ra, numpy.arangecó thể được sử dụng.


2

Nó có thể được thực hiện bằng thư viện Numpy. Hàm arange () cho phép các bước trong float. Tuy nhiên, nó trả về một mảng numpy có thể được chuyển đổi thành danh sách bằng cách sử dụng tolist () để thuận tiện cho chúng tôi.

for i in np.arange(0, 1, 0.1).tolist():
   print i

2

Câu trả lời của tôi tương tự với những người khác sử dụng map (), không cần NumPy và không sử dụng lambda (mặc dù bạn có thể). Để nhận danh sách các giá trị float từ 0,0 đến t_max theo các bước của dt:

def xdt(n):
    return dt*float(n)
tlist  = map(xdt, range(int(t_max/dt)+1))

2

Chưa có ai đề cập đến giải pháp được đề xuất trong tài liệu Python 3 :

Xem thêm:

  • Công thức không gian lins cho thấy cách triển khai một phiên bản phạm vi lười biếng phù hợp với các ứng dụng dấu phẩy động.

Sau khi được xác định, công thức rất dễ sử dụng và không yêu cầu numpyhoặc bất kỳ thư viện bên ngoài nào khác, nhưng các chức năng như thế nào numpy.linspace(). Lưu ý rằng thay vì một stepđối số, đối số thứ ba numchỉ định số lượng giá trị mong muốn, ví dụ:

print(linspace(0, 10, 5))
# linspace(0, 10, 5)
print(list(linspace(0, 10, 5)))
# [0.0, 2.5, 5.0, 7.5, 10]

Tôi trích dẫn một phiên bản sửa đổi của công thức Python 3 đầy đủ từ Andrew Barnert bên dưới:

import collections.abc
import numbers

class linspace(collections.abc.Sequence):
    """linspace(start, stop, num) -> linspace object

    Return a virtual sequence of num numbers from start to stop (inclusive).

    If you need a half-open range, use linspace(start, stop, num+1)[:-1].
    """
    def __init__(self, start, stop, num):
        if not isinstance(num, numbers.Integral) or num <= 1:
            raise ValueError('num must be an integer > 1')
        self.start, self.stop, self.num = start, stop, num
        self.step = (stop-start)/(num-1)
    def __len__(self):
        return self.num
    def __getitem__(self, i):
        if isinstance(i, slice):
            return [self[x] for x in range(*i.indices(len(self)))]
        if i < 0:
            i = self.num + i
        if i >= self.num:
            raise IndexError('linspace object index out of range')
        if i == self.num-1:
            return self.stop
        return self.start + i*self.step
    def __repr__(self):
        return '{}({}, {}, {})'.format(type(self).__name__,
                                       self.start, self.stop, self.num)
    def __eq__(self, other):
        if not isinstance(other, linspace):
            return False
        return ((self.start, self.stop, self.num) ==
                (other.start, other.stop, other.num))
    def __ne__(self, other):
        return not self==other
    def __hash__(self):
        return hash((type(self), self.start, self.stop, self.num))

2

Để chống lại các vấn đề chính xác nổi, bạn có thể sử dụng Decimalmô-đun .

Điều này đòi hỏi một nỗ lực thêm để chuyển đổi Decimaltừ inthoặc floattrong khi viết mã, nhưng thay vào đó bạn có thể vượt qua strvà sửa đổi chức năng nếu loại tiện lợi đó thực sự cần thiết.

from decimal import Decimal
from decimal import Decimal as D


def decimal_range(*args):

    zero, one = Decimal('0'), Decimal('1')

    if len(args) == 1:
        start, stop, step = zero, args[0], one
    elif len(args) == 2:
        start, stop, step = args + (one,)
    elif len(args) == 3:
        start, stop, step = args
    else:
        raise ValueError('Expected 1 or 2 arguments, got %s' % len(args))

    if not all([type(arg) == Decimal for arg in (start, stop, step)]):
        raise ValueError('Arguments must be passed as <type: Decimal>')

    # neglect bad cases
    if (start == stop) or (start > stop and step >= zero) or \
                          (start < stop and step <= zero):
        return []

    current = start
    while abs(current) < abs(stop):
        yield current
        current += step

Đầu ra mẫu -

list(decimal_range(D('2')))
# [Decimal('0'), Decimal('1')]
list(decimal_range(D('2'), D('4.5')))
# [Decimal('2'), Decimal('3'), Decimal('4')]
list(decimal_range(D('2'), D('4.5'), D('0.5')))
# [Decimal('2'), Decimal('2.5'), Decimal('3.0'), Decimal('3.5'), Decimal('4.0')]
list(decimal_range(D('2'), D('4.5'), D('-0.5')))
# []
list(decimal_range(D('2'), D('-4.5'), D('-0.5')))
# [Decimal('2'),
#  Decimal('1.5'),
#  Decimal('1.0'),
#  Decimal('0.5'),
#  Decimal('0.0'),
#  Decimal('-0.5'),
#  Decimal('-1.0'),
#  Decimal('-1.5'),
#  Decimal('-2.0'),
#  Decimal('-2.5'),
#  Decimal('-3.0'),
#  Decimal('-3.5'),
#  Decimal('-4.0')]

2
DecimalĐầu vào tương tự , np.arangehoạt động như nhau:np.arange(Decimal('-2.0'), Decimal('2.0'), Decimal('0.1'))
hpaulj

2
Đúng, cảm ơn. Mặc dù, điều đó sẽ cần một lib (numpy) bên ngoài.
shad0w_wa1k3r

1

Thêm tự động sửa cho khả năng có dấu hiệu không chính xác trên bước:

def frange(start,step,stop):
    step *= 2*((stop>start)^(step<0))-1
    return [start+i*step for i in range(int((stop-start)/step))]

1

Giải pháp của tôi:

def seq(start, stop, step=1, digit=0):
    x = float(start)
    v = []
    while x <= stop:
        v.append(round(x,digit))
        x += step
    return v

1

Giải pháp tốt nhất: không có lỗi làm tròn số
_________________________________________________________________________________

>>> step = .1
>>> N = 10     # number of data points
>>> [ x / pow(step, -1) for x in range(0, N + 1) ]

[0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]

Giới thiệu

, đối với phạm vi được đặt thay vì đặt điểm dữ liệu (ví dụ: hàm liên tục), hãy sử dụng:

>>> step = .1
>>> rnge = 1     # NOTE range = 1, i.e. span of data points
>>> N = int(rnge / step
>>> [ x / pow(step,-1) for x in range(0, N + 1) ]

[0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]

Để thực hiện một chức năng: thay thế x / pow(step, -1)bằng f( x / pow(step, -1) )và xác định f.
Ví dụ:

>>> import math
>>> def f(x):
        return math.sin(x)

>>> step = .1
>>> rnge = 1     # NOTE range = 1, i.e. span of data points
>>> N = int(rnge / step)
>>> [ f( x / pow(step,-1) ) for x in range(0, N + 1) ]

[0.0, 0.09983341664682815, 0.19866933079506122, 0.29552020666133955, 0.3894183423086505, 
 0.479425538604203, 0.5646424733950354, 0.644217687237691, 0.7173560908995228,
 0.7833269096274834, 0.8414709848078965]

1

bắt đầu và dừng lại đã bao gồm chứ không phải cái này hay cái kia (thường là loại trừ dừng) và không nhập khẩu, và sử dụng máy phát điện

def rangef(start, stop, step, fround=5):
    """
    Yields sequence of numbers from start (inclusive) to stop (inclusive)
    by step (increment) with rounding set to n digits.

    :param start: start of sequence
    :param stop: end of sequence
    :param step: int or float increment (e.g. 1 or 0.001)
    :param fround: float rounding, n decimal places
    :return:
    """
    try:
        i = 0
        while stop >= start and step > 0:
            if i==0:
                yield start
            elif start >= stop:
                yield stop
            elif start < stop:
                if start == 0:
                    yield 0
                if start != 0:
                    yield start
            i += 1
            start += step
            start = round(start, fround)
        else:
            pass
    except TypeError as e:
        yield "type-error({})".format(e)
    else:
        pass


# passing
print(list(rangef(-100.0,10.0,1)))
print(list(rangef(-100,0,0.5)))
print(list(rangef(-1,1,0.2)))
print(list(rangef(-1,1,0.1)))
print(list(rangef(-1,1,0.05)))
print(list(rangef(-1,1,0.02)))
print(list(rangef(-1,1,0.01)))
print(list(rangef(-1,1,0.005)))
# failing: type-error:
print(list(rangef("1","10","1")))
print(list(rangef(1,10,"1")))

Python 3.6.2 (v3.6.2: 5fd33b5, ngày 8 tháng 7 năm 2017, 04:57:36) [MSC v.1900 64 bit (AMD64)]


1

Tôi biết tôi đến bữa tiệc muộn ở đây, nhưng đây là một giải pháp máy phát tầm thường hoạt động trong 3.6:

def floatRange(*args):
    start, step = 0, 1
    if len(args) == 1:
        stop = args[0]
    elif len(args) == 2:
        start, stop = args[0], args[1]
    elif len(args) == 3:
        start, stop, step = args[0], args[1], args[2]
    else:
        raise TypeError("floatRange accepts 1, 2, or 3 arguments. ({0} given)".format(len(args)))
    for num in start, step, stop:
        if not isinstance(num, (int, float)):
            raise TypeError("floatRange only accepts float and integer arguments. ({0} : {1} given)".format(type(num), str(num)))
    for x in range(int((stop-start)/step)):
        yield start + (x * step)
    return

sau đó bạn có thể gọi nó giống như bản gốc range()... không có xử lý lỗi, nhưng hãy cho tôi biết nếu có lỗi có thể bị bắt một cách hợp lý và tôi sẽ cập nhật. hoặc bạn có thể cập nhật nó. đây là StackOverflow.


0

Đây là giải pháp của tôi hoạt động tốt với float_range (-1, 0, 0,01) và hoạt động mà không có lỗi biểu diễn dấu phẩy động. Nó không phải là rất nhanh, nhưng hoạt động tốt:

from decimal import Decimal

def get_multiplier(_from, _to, step):
    digits = []
    for number in [_from, _to, step]:
        pre = Decimal(str(number)) % 1
        digit = len(str(pre)) - 2
        digits.append(digit)
    max_digits = max(digits)
    return float(10 ** (max_digits))


def float_range(_from, _to, step, include=False):
    """Generates a range list of floating point values over the Range [start, stop]
       with step size step
       include=True - allows to include right value to if possible
       !! Works fine with floating point representation !!
    """
    mult = get_multiplier(_from, _to, step)
    # print mult
    int_from = int(round(_from * mult))
    int_to = int(round(_to * mult))
    int_step = int(round(step * mult))
    # print int_from,int_to,int_step
    if include:
        result = range(int_from, int_to + int_step, int_step)
        result = [r for r in result if r <= int_to]
    else:
        result = range(int_from, int_to, int_step)
    # print result
    float_result = [r / mult for r in result]
    return float_result


print float_range(-1, 0, 0.01,include=False)

assert float_range(1.01, 2.06, 5.05 % 1, True) ==\
[1.01, 1.06, 1.11, 1.16, 1.21, 1.26, 1.31, 1.36, 1.41, 1.46, 1.51, 1.56, 1.61, 1.66, 1.71, 1.76, 1.81, 1.86, 1.91, 1.96, 2.01, 2.06]

assert float_range(1.01, 2.06, 5.05 % 1, False)==\
[1.01, 1.06, 1.11, 1.16, 1.21, 1.26, 1.31, 1.36, 1.41, 1.46, 1.51, 1.56, 1.61, 1.66, 1.71, 1.76, 1.81, 1.86, 1.91, 1.96, 2.01]

0

Tôi chỉ là người mới bắt đầu, nhưng tôi có cùng một vấn đề, khi mô phỏng một số tính toán. Đây là cách tôi đã cố gắng để làm việc này, dường như đang làm việc với các bước thập phân.

Tôi cũng khá lười biếng và vì vậy tôi cảm thấy khó khăn khi viết hàm phạm vi của riêng mình.

Về cơ bản những gì tôi đã được thay đổi của tôi xrange(0.0, 1.0, 0.01)để xrange(0, 100, 1)và sử dụng các bộ phận bằng 100.0bên trong vòng lặp. Tôi cũng lo ngại, nếu có những sai lầm làm tròn. Vì vậy, tôi quyết định thử nghiệm, cho dù có bất kỳ. Bây giờ tôi nghe nói, nếu ví dụ 0.01từ một phép tính không chính xác là số float 0.01so sánh chúng sẽ trả về Sai (nếu tôi sai, xin vui lòng cho tôi biết).

Vì vậy, tôi quyết định kiểm tra xem giải pháp của tôi có hoạt động cho phạm vi của mình hay không bằng cách chạy thử nghiệm ngắn:

for d100 in xrange(0, 100, 1):
    d = d100 / 100.0
    fl = float("0.00"[:4 - len(str(d100))] + str(d100))
    print d, "=", fl , d == fl

Và nó được in True cho mỗi.

Bây giờ, nếu tôi nhận được nó hoàn toàn sai, xin vui lòng cho tôi biết.


0

Điều này một lót sẽ không làm lộn xộn mã của bạn. Dấu hiệu của tham số bước là quan trọng.

def frange(start, stop, step):
    return [x*step+start for x in range(0,round(abs((stop-start)/step)+0.5001),
        int((stop-start)/step<0)*-2+1)]
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.