Existe uma maneira de alternar entre 0 e 1 por 0,1?
Eu pensei que poderia fazê-lo da seguinte forma, mas falhou:
for i in range(0, 1, 0.1):
print i
Em vez disso, diz que o argumento step não pode ser zero, o que eu não esperava.
python
floating-point
range
Evan Fosmark
fonte
fonte
itertools.takewhile
eitertools.count
.drange
Porém, não é melhor do que o desempenho.seq
ferramenta GNU coreutils permite fazerseq 0 0.1 1
sem erros de arredondamento!seq
usa olong double
tipo C internamente e está sujeito a erros de arredondamento. Por exemplo, na minha máquina,seq 0 0.1 1
fornece1
como última saída (conforme o esperado), masseq 1 0.1 2
fornece1.9
como a última saída (ao invés do esperado2
).itertools.takewhile(lambda x: (x+0.05)<1, itertools.count(0,0.1))
ouitertools.islice(itertools.count(0,0.1), 10)
(depois de terimport itertools
), embora eu não tenha testado que é mais eficienteRespostas:
Em vez de usar uma etapa decimal diretamente, é muito mais seguro expressar isso em termos de quantos pontos você deseja. Caso contrário, o erro de arredondamento de ponto flutuante provavelmente fornecerá um resultado errado.
Você pode usar a função linspace da biblioteca NumPy (que não faz parte da biblioteca padrão, mas é relativamente fácil de obter).
linspace
leva vários pontos para retornar e também permite especificar se deve ou não incluir o terminal correto:Se você realmente deseja usar um valor de etapa de ponto flutuante, pode, com
numpy.arange
.Erro de arredondamento de ponto flutuante vai causar problemas, no entanto. Aqui está um caso simples em que o erro de arredondamento causa
arange
uma matriz de comprimento 4, quando deve produzir apenas 3 números:fonte
np.linspace(1.,1.3,4)
enp.arange(1.,1.3,0.1)
dar exatamente a mesma saída[start,stop)
(ou seja, excluindostop
), portanto, não se espera que 1.3 seja incluído na lista. Veja esta pergunta para saber por que ela ainda está incluída e o que fazer contra ela.O range do Python () só pode fazer números inteiros, não pontos flutuantes. No seu caso específico, você pode usar uma compreensão de lista:
(Substitua a chamada para variar com essa expressão.)
Para o caso mais geral, você pode escrever uma função ou gerador personalizado.
fonte
(x * 0.1 for x in range(0, 10))
.x/10
em vez dex * 0.1
: D Nada de especial na verdade, mas alguns números em que haverá mais preciso, por exemplo, para3*0.1
que você começa0.30000000000000004
, enquanto que para 3/10 você começa0.3
:)from __future__ import division; 3/10
retorna 0,3. Esse comportamento é o padrão no Python 3.x.Com base no 'xrange ([start], stop [, step])' , você pode definir um gerador que aceita e produz qualquer tipo que você escolher (atenda aos tipos de suporte
+
e<
):fonte
Aumente a magnitude do
i
loop e reduza-o quando necessário.EDIT: Sinceramente, não me lembro por que pensei que funcionaria sintaticamente
Isso deve ter a saída desejada.
fonte
for i * 100 in range(0, 100, 10)
: SyntaxError: Não é possível atribuir ao operadorscipy
possui uma função integradaarange
que generaliza orange()
construtor do Python para satisfazer seus requisitos de manipulação de float.from scipy import arange
fonte
arange
você pode encontrar em numpy:>>> import scipy >>> import numpy >>> numpy.arange is scipy.arange
retornaráTrue
.from nump import arange as range
NumPy é um pouco exagerado, eu acho.
De um modo geral, fazer um passo a passo
1/x
comy
você faria(
1/x
produziu menos ruído quando testei).fonte
Semelhante à função de R
seq
, esta retorna uma sequência em qualquer ordem, dado o valor correto da etapa. O último valor é igual ao valor de parada.Resultados
fonte
seq(0.5, 3.0)
retorna[0.5, 1.5, 2.5, 3.5]
. Para evitar últimas entradas estar fora-de-gama, substituan = int(round(...
comn = int(floor(...
com a linhafrom math import floor
na parte superior (acimadef seq(...
).floor
for usado,seq(0.2, 0.9, 0.1)
vai deixar de atingir endpoint direita e vai voltar[0.2, 0.30000000000000004, 0.4, 0.5, 0.6000000000000001, 0.7, 0.8]
A função interna range () retorna uma sequência de valores inteiros, receio, portanto você não pode usá-la para executar uma etapa decimal.
Eu diria que basta usar um loop while:
Se você estiver curioso, o Python está convertendo seu 0,1 para 0, e é por isso que está lhe dizendo que o argumento não pode ser zero.
fonte
.1
10 vezes não é o mesmo que adicionar1
! docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.htmlAqui está uma solução usando itertools :
Exemplo de uso:
fonte
no Python 2.7x fornece o resultado de:
mas se você usar:
fornece o desejado:
fonte
fonte
E se você fizer isso com frequência, convém salvar a lista gerada
r
fonte
more_itertools
é uma biblioteca de terceiros que implementa umanumeric_range
ferramenta:Resultado
Essa ferramenta também funciona para
Decimal
eFraction
.fonte
Minhas versões usam a função de intervalo original para criar índices multiplicativos para o turno. Isso permite a mesma sintaxe da função de intervalo original. Eu fiz duas versões, uma usando float e outra usando Decimal, porque descobri que em alguns casos eu queria evitar o desvio de arredondamento introduzido pela aritmética de ponto flutuante.
É consistente com os resultados do conjunto vazio, como no intervalo / intervalo.
Passar apenas um único valor numérico para qualquer função retornará a saída da faixa padrão para o valor do teto inteiro do parâmetro de entrada (portanto, se você fornecesse 5.5, retornaria a faixa (6).)
Edit: o código abaixo já está disponível como pacote no pypi: Franges
fonte
frange
funcionar se parar éNone
? Essa parte do código nem considera mais o tamanho da etapa.range
tem duas assinaturas :,range(stop)
que assume um padrãostart=0, step=1
erange(start, stop, step)
, onde nenhuma suposição é feita.frange
reflete isso. Ao usar arange(stop)
assinatura, ambosfrange
edrange
iniciam em 0 e aumentam em 1, para que o comportamento deles seja idêntico aorange(stop)
comportamento normal , com a parada arredondada para o número inteiro mais próximo.Esta é a minha solução para obter intervalos com etapas de flutuação.
Usando esta função, não é necessário importar numpy nem instalá-lo.
Tenho certeza de que poderia ser melhorado e otimizado. Sinta-se à vontade para publicá-lo aqui.
A saída é:
fonte
Para a integridade da boutique, uma solução funcional:
fonte
Você pode usar esta função:
fonte
list(frange(99.8, 100.1, 0.1)) => [99.7, 99.80000000000001, 99.9]
O truque para evitar arredondamento problema é usar um número separado para percorrer o intervalo, que começa e meia o passo à frente de início .
Como alternativa,
numpy.arange
pode ser usado.fonte
Isso pode ser feito usando a biblioteca Numpy. A função arange () permite etapas em flutuação. Mas, ele retorna uma matriz numpy que pode ser convertida em lista usando tolist () para nossa conveniência.
fonte
Minha resposta é semelhante a outras que usam map (), sem a necessidade de NumPy e sem usar lambda (embora você possa). Para obter uma lista de valores flutuantes de 0,0 a t_max nas etapas de dt:
fonte
Ninguém surpreso ainda mencionou a solução recomendada nos documentos do Python 3 :
Uma vez definida, a receita é fácil de usar e não requer
numpy
ou quaisquer outras bibliotecas externas, mas funciona comonumpy.linspace()
. Observe que, em vez de umstep
argumento, o terceironum
argumento especifica o número de valores desejados, por exemplo:Cito uma versão modificada da receita completa do Python 3 de Andrew Barnert abaixo:
fonte
Para combater os problemas de precisão do flutuador, você pode usar o
Decimal
módulo .Isso exige um esforço extra de conversão
Decimal
deint
ou parafloat
escrever o código, mas você pode passarstr
e modificar a função se esse tipo de conveniência for realmente necessário.Saídas de amostra -
fonte
Decimal
entradas,np.arange
funciona da mesma:np.arange(Decimal('-2.0'), Decimal('2.0'), Decimal('0.1'))
Adicione a correção automática para a possibilidade de um sinal incorreto na etapa:
fonte
Minha solução:
fonte
Melhor solução: sem erro de arredondamento
_________________________________________________________________________________
_________________________________________________________________________________
Ou, para um intervalo definido em vez de pontos de dados definidos (por exemplo, função contínua), use:
Para implementar uma função: substitua
x / pow(step, -1)
porf( x / pow(step, -1) )
e definaf
.Por exemplo:
fonte
start e stop são inclusivos em vez de um ou outro (geralmente o stop é excluído) e sem importações e usando geradores
fonte
Eu sei que estou atrasado para a festa aqui, mas aqui está uma solução de gerador trivial que está funcionando na 3.6:
você pode chamá-lo exatamente como o original
range()
... não há tratamento de erros, mas deixe-me saber se há um erro que possa ser razoavelmente detectado, e eu atualizarei. ou você pode atualizá-lo. isso é StackOverflow.fonte
Aqui está minha solução que funciona bem com float_range (-1, 0, 0,01) e funciona sem erros de representação de ponto flutuante. Não é muito rápido, mas funciona bem:
fonte
Sou apenas iniciante, mas tive o mesmo problema ao simular alguns cálculos. Aqui está como eu tentei resolver isso, o que parece estar funcionando com etapas decimais.
Eu também sou muito preguiçoso e, por isso, achei difícil escrever minha própria função de intervalo.
Basicamente, o que fiz foi alterado
xrange(0.0, 1.0, 0.01)
paraxrange(0, 100, 1)
e usado a divisão100.0
dentro do loop. Eu também estava preocupado, se haverá erros de arredondamento. Então eu decidi testar, se há algum. Agora ouvi dizer que, se, por exemplo,0.01
de um cálculo não for exatamente o float,0.01
comparando-os, retorne False (se estiver errado, por favor me avise).Então, decidi testar se minha solução funcionaria para meu intervalo executando um pequeno teste:
E imprimiu True para cada um.
Agora, se estiver errado, informe-me.
fonte
Este liner não irá desorganizar seu código. O sinal do parâmetro step é importante.
fonte