Apakah ada cara untuk melangkah antara 0 dan 1 dengan 0,1?
Saya pikir saya bisa melakukannya seperti berikut, tetapi gagal:
for i in range(0, 1, 0.1):
print i
Sebaliknya, ia mengatakan bahwa argumen langkah tidak boleh nol, yang tidak saya harapkan.
python
floating-point
range
Evan Fosmark
sumber
sumber
itertools.takewhile
danitertools.count
. Itu tidak lebih baik daridrange
segi kinerja.seq
alat dalam GNU coreutils memungkinkan seseorang untuk melakukannyaseq 0 0.1 1
tanpa kesalahan pembulatan!seq
menggunakan Clong double
jenis internal, dan adalah tunduk pada kesalahan pembulatan. Misalnya pada mesin saya,seq 0 0.1 1
berikan1
sebagai output terakhir (seperti yang diharapkan), tetapiseq 1 0.1 2
berikan1.9
sebagai output terakhir (bukan yang diharapkan2
).itertools.takewhile(lambda x: (x+0.05)<1, itertools.count(0,0.1))
atauitertools.islice(itertools.count(0,0.1), 10)
(setelah Anda milikiimport itertools
), meskipun saya belum menguji mana yang lebih efisienJawaban:
Daripada menggunakan langkah desimal secara langsung, jauh lebih aman untuk mengungkapkan ini dalam hal berapa banyak poin yang Anda inginkan. Jika tidak, kesalahan pembulatan floating-point cenderung memberi Anda hasil yang salah.
Anda dapat menggunakan fungsi linspace dari pustaka NumPy (yang bukan bagian dari pustaka standar tetapi relatif mudah diperoleh).
linspace
mengambil sejumlah poin untuk kembali, dan juga memungkinkan Anda menentukan apakah akan menyertakan titik akhir yang tepat atau tidak:Jika Anda benar-benar ingin menggunakan nilai langkah floating-point, Anda bisa, dengan
numpy.arange
.Kesalahan pembulatan titik-mengambang akan menyebabkan masalah. Inilah kasus sederhana di mana kesalahan pembulatan menyebabkan
arange
menghasilkan array panjang-4 ketika seharusnya hanya menghasilkan 3 angka:sumber
np.linspace(1.,1.3,4)
dannp.arange(1.,1.3,0.1)
memberikan hasil yang persis sama[start,stop)
(yaitu tidak termasukstop
), jadi orang tidak akan mengharapkan 1.3 untuk dimasukkan dalam daftar. Lihat pertanyaan ini untuk alasan mengapa hal itu masih termasuk dan apa yang harus dilakukan terhadapnya.Rentang Python () hanya dapat melakukan bilangan bulat, bukan titik mengambang. Dalam kasus spesifik Anda, Anda dapat menggunakan pemahaman daftar sebagai gantinya:
(Ganti panggilan untuk menjangkau dengan ekspresi itu.)
Untuk kasus yang lebih umum, Anda mungkin ingin menulis fungsi atau generator khusus.
sumber
(x * 0.1 for x in range(0, 10))
.x/10
bukannyax * 0.1
: D Tidak ada yang istimewa sebenarnya, tetapi beberapa angka dalam akan ada lebih tepat, misalnya untuk3*0.1
Anda mendapatkan0.30000000000000004
, sedangkan untuk 3/10 Anda mendapatkan0.3
:)from __future__ import division; 3/10
mengembalikan 0,3. Perilaku ini adalah default dalam Python 3.x.Membangun di 'xrange ([mulai], berhenti [, langkah])' , Anda dapat menentukan generator yang menerima dan menghasilkan jenis apa pun yang Anda pilih (tetap pada jenis yang mendukung
+
dan<
):sumber
Tingkatkan besarnya
i
untuk loop dan kemudian kurangi saat Anda membutuhkannya.EDIT: Jujur saya tidak ingat mengapa saya pikir itu akan bekerja secara sintaksis
Itu harus memiliki output yang diinginkan.
sumber
for i * 100 in range(0, 100, 10)
: SyntaxError: tidak dapat menetapkan ke operatorscipy
memiliki fungsiarange
bawaan yang menyamaratakanrange()
konstruktor Python untuk memenuhi kebutuhan penanganan float Anda.from scipy import arange
sumber
arange
Anda temukan di numpy:>>> import scipy >>> import numpy >>> numpy.arange is scipy.arange
akan kembaliTrue
.from nump import arange as range
NumPy agak berlebihan, saya pikir.
Secara umum, untuk melakukan langkah-demi-
1/x
sampaiy
Anda akan melakukan(
1/x
Menghasilkan kebisingan pembulatan kurang ketika saya diuji).sumber
Mirip dengan fungsi R
seq
, yang ini mengembalikan urutan dalam urutan apa pun yang diberikan nilai langkah yang benar. Nilai terakhir sama dengan nilai stop.Hasil
sumber
seq(0.5, 3.0)
kembali[0.5, 1.5, 2.5, 3.5]
. Untuk menghindari entri terakhir berada di luar jangkauan, gantikann = int(round(...
dengann = int(floor(...
barisfrom math import floor
di atas (di atasdef seq(...
).floor
digunakan,seq(0.2, 0.9, 0.1)
akan gagal mencapai titik akhir kanan dan akan kembali[0.2, 0.30000000000000004, 0.4, 0.5, 0.6000000000000001, 0.7, 0.8]
Rentang () fungsi bawaan mengembalikan urutan nilai integer, saya khawatir, jadi Anda tidak dapat menggunakannya untuk melakukan langkah desimal.
Saya akan mengatakan cukup gunakan loop sementara:
Jika Anda penasaran, Python mengonversi 0,1 menjadi 0, itulah sebabnya ia memberi tahu Anda bahwa argumennya tidak boleh nol.
sumber
.1
10 kali tidak sama dengan menambahkan1
! docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.htmlInilah solusi menggunakan itertools :
Contoh Penggunaan:
sumber
di Python 2.7x memberi Anda hasil:
tetapi jika Anda menggunakan:
memberi Anda yang diinginkan:
sumber
sumber
Dan jika Anda sering melakukan ini, Anda mungkin ingin menyimpan daftar yang dihasilkan
r
sumber
more_itertools
adalah perpustakaan pihak ketiga yang mengimplementasikannumeric_range
alat:Keluaran
Alat ini juga berfungsi untuk
Decimal
danFraction
.sumber
Versi saya menggunakan fungsi rentang asli untuk membuat indeks multiplikasi untuk perubahan tersebut. Ini memungkinkan sintaks yang sama ke fungsi rentang asli. Saya telah membuat dua versi, satu menggunakan float, dan satu menggunakan Decimal, karena saya menemukan bahwa dalam beberapa kasus saya ingin menghindari penyimpangan pembulatan yang diperkenalkan oleh aritmatika floating point.
Ini konsisten dengan hasil set kosong seperti dalam rentang / xrange.
Melewati hanya satu nilai numerik ke salah satu fungsi akan mengembalikan output rentang standar ke nilai langit-langit integer dari parameter input (jadi jika Anda memberikannya 5,5, itu akan mengembalikan kisaran (6).)
Sunting: kode di bawah ini sekarang tersedia sebagai paket di pypi: Franges
sumber
frange
bekerja jika berhentiNone
? Bagian kode itu bahkan tidak mempertimbangkan ukuran langkah lagi.range
memiliki dua tanda tangan :,range(stop)
yang mengasumsikan defaultstart=0, step=1
, danrange(start, stop, step)
, di mana tidak ada asumsi yang dibuat.frange
mencerminkan itu. Bila menggunakanrange(stop)
tanda tangan, baikfrange
dandrange
mulai 0 dan kenaikan sebesar 1, sehingga perilaku mereka identik dengan teraturrange(stop)
perilaku dengan berhenti dibulatkan ke bilangan bulat terdekat.Ini adalah solusi saya untuk mendapatkan rentang dengan langkah float.
Menggunakan fungsi ini tidak perlu mengimpor numpy, atau menginstalnya.
Saya cukup yakin itu bisa ditingkatkan dan dioptimalkan. Merasa bebas untuk melakukannya dan mempostingnya di sini.
Outputnya adalah:
sumber
Untuk kelengkapan butik, solusi fungsional:
sumber
Anda dapat menggunakan fungsi ini:
sumber
list(frange(99.8, 100.1, 0.1)) => [99.7, 99.80000000000001, 99.9]
Trik untuk menghindari putaran-off masalah adalah dengan menggunakan nomor yang terpisah untuk bergerak melalui jangkauan, yang dimulai dan setengah yang langkah maju dari awal .
Atau,
numpy.arange
bisa digunakan.sumber
Itu bisa dilakukan menggunakan Numpy library. Fungsi arange () memungkinkan langkah-langkah dalam float. Tapi, ia mengembalikan array numpy yang dapat dikonversi ke daftar menggunakan tolist () untuk kenyamanan kita.
sumber
Jawaban saya mirip dengan yang lain menggunakan peta (), tanpa perlu NumPy, dan tanpa menggunakan lambda (meskipun Anda bisa). Untuk mendapatkan daftar nilai float dari 0,0 hingga t_max dalam langkah-langkah dt:
sumber
Terkejut belum ada yang menyebutkan solusi yang disarankan dalam Python 3 docs :
Setelah ditentukan, resep mudah digunakan dan tidak memerlukan
numpy
atau perpustakaan eksternal lainnya, tetapi fungsinya sepertinumpy.linspace()
. Perhatikan bahwa alih-alihstep
argumen,num
argumen ketiga menentukan jumlah nilai yang diinginkan, misalnya:Saya mengutip versi modifikasi dari resep Python 3 lengkap dari Andrew Barnert di bawah ini:
sumber
Untuk mengatasi masalah presisi float, Anda dapat menggunakan
Decimal
modul .Ini menuntut upaya ekstra untuk mengubah
Decimal
dariint
ataufloat
saat menulis kode, tetapi Anda bisa meneruskanstr
dan memodifikasi fungsi jika memang dibutuhkan kenyamanan semacam itu.Output sampel -
sumber
Decimal
input yang serupa ,np.arange
bekerja sama:np.arange(Decimal('-2.0'), Decimal('2.0'), Decimal('0.1'))
Tambahkan koreksi otomatis untuk kemungkinan tanda yang salah pada langkah:
sumber
Solusi saya:
sumber
Solusi Terbaik: tidak ada kesalahan pembulatan
_________________________________________________________________________________
_________________________________________________________________________________
Atau, untuk rentang yang ditetapkan alih-alih mengatur titik data (misalnya fungsi berkelanjutan), gunakan:
Untuk mengimplementasikan fungsi: ganti
x / pow(step, -1)
denganf( x / pow(step, -1) )
, dan tentukanf
.Sebagai contoh:
sumber
start dan stop bersifat inklusif dan bukan yang satu (biasanya stop dikecualikan) dan tanpa impor, dan menggunakan generator
sumber
Saya tahu saya terlambat ke pesta di sini, tapi inilah solusi generator sepele yang bekerja di 3.6:
maka Anda dapat memanggilnya seperti aslinya
range()
... tidak ada penanganan kesalahan, tetapi beri tahu saya jika ada kesalahan yang dapat ditangkap secara wajar, dan saya akan memperbarui. atau Anda dapat memperbaruinya. ini adalah StackOverflow.sumber
Berikut adalah solusi saya yang berfungsi baik dengan float_range (-1, 0, 0,01) dan berfungsi tanpa kesalahan representasi floating point. Ini tidak terlalu cepat, tetapi berfungsi dengan baik:
sumber
Saya hanya pemula, tetapi saya memiliki masalah yang sama, ketika mensimulasikan beberapa perhitungan. Inilah cara saya mencoba menyelesaikannya, yang tampaknya bekerja dengan langkah desimal.
Saya juga cukup malas dan jadi saya merasa sulit untuk menulis fungsi jangkauan saya sendiri.
Pada dasarnya apa yang saya lakukan adalah mengubah
xrange(0.0, 1.0, 0.01)
ke sayaxrange(0, 100, 1)
dan menggunakan pembagian dengan100.0
di dalam loop. Saya juga khawatir, apakah akan ada kesalahan pembulatan. Jadi saya memutuskan untuk menguji, apakah ada. Sekarang saya dengar, kalau misalnya0.01
dari perhitungan tidak persis float0.01
membandingkan mereka harus mengembalikan False (jika saya salah, tolong beri tahu saya).Jadi saya memutuskan untuk menguji apakah solusi saya akan bekerja untuk kisaran saya dengan menjalankan tes singkat:
Dan itu dicetak Benar untuk masing-masing.
Sekarang, jika saya benar-benar salah, tolong beri tahu saya.
sumber
Liner satu ini tidak akan mengacaukan kode Anda. Tanda parameter langkah penting.
sumber