你可以在这个 for 循环中使用浮点数吗?

我需要帮助。我试图让我的 for 循环使用小数,但我的代码不接受浮点数,我不知道下一步该做什么。谁能指出我哪里出错了?

它是用于在用户定义的步骤(Delta)中将摄氏温度转换为华氏温度的代码。这里是:

def main():

    # Handshake
    print("This program will convert a range of Celsius degrees to")
    print("Fahrenheit degrees based on your input.")

    # Ask and read low end of range
    Rangelow = eval(input("Enter the low end of your range: "))

    # Ask and read top end of range
    Rangehigh = 1 + eval(input("Enter the high end of your range: "))

    # Ask and read Delta
    Delta = eval(input("Enter the Delta for your range: "))

    #Display output
    print("Celsius to Fahrenheit by", Delta)
    for i in range(Rangelow, Rangehigh, Delta):
        print(i, "               ", 9/5 * i + 32)

main()

这是我的意思的一个例子:

该程序将根据您的输入将摄氏温度范围转换为华氏温度。输入范围的低端:3.8 输入范围的高端:14.7 输入范围的增量:1.1 摄氏度到华氏度 1.1 回溯(最近一次调用最后一次):文件“C:UsersjarreDesktopPython ProgramsConversion.py”,行27,在 main() 文件“C:UsersjarreDesktopPython ProgramsConversion.py”中,第 22 行,在 main for i in range(Rangelow, Rangehigh + 1, Delta): TypeError: 'float' object cannot be compiled as an integer

我应该注意到问题似乎出在输入上,在输入转换后输出没有问题抛出小数。

stack overflow Can you use float numbers in this for loop?
原文答案
author avatar

接受的答案

您不能使用内置来进行浮点/小数增量,但构建自己的生成器相当容易:

def decimal_range(start, stop, increment):
    while start < stop: # and not math.isclose(start, stop): Py>3.5
        yield start
        start += increment

for i in decimal_range(Rangelow, Rangehigh, Delta):
    ...

或者你可以使用 numpy 但这感觉就像一把大锤敲碎了坚果:

import numpy as np
for i in np.arange(Rangelow, Rangehigh, Delta):
    ...

答案:

作者头像
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import decimal

def range_decimal(start, stop, step, stop_inclusive=False):
    """ The Python range() function, using decimals.  A decimal loop_value generator.

    Note: The decimal math (addition) defines the rounding.

    If the stop is None, then:
        stop = start
        start = 0 (zero)

    If the step is 0 (zero) or None, then:
        if (stop < start) then step = -1 (minus one)
        if (stop >= start) then step = 1 (one)

    Example:
        for index in range_decimal(0, 1.0, '.1', stop_inclusive=True):
            print(index)

    :param start: The loop start value
    :param stop: The loop stop value
    :param step: The loop step value
    :param stop_inclusive: Include the stop value in the loop's yield generator: False = excluded ; True = included
    :return: The loop generator's yield increment value (decimal)
    """
    try:
        # Input argument(s) error check
        zero = decimal.Decimal('0')

        if start is None:
            start = zero

        if not isinstance(start, decimal.Decimal):
            start = decimal.Decimal(f'{start}')

        if stop is None:
            stop = start
            start = zero

        if not isinstance(stop, decimal.Decimal):
            stop = decimal.Decimal(f'{stop}')

        if step is None:
            step = decimal.Decimal('-1' if stop < start else '1')

        if not isinstance(step, decimal.Decimal):
            step = decimal.Decimal(f'{step}')

        if step == zero:
            step = decimal.Decimal('-1' if stop < start else '1')

        # Check for valid loop conditions
        if start == stop or (start < stop and step < zero) or (start > stop and step > zero):
            return  # Not valid: no loop

        # Case: increment step ( > 0 )
        if step > zero:
            while start < stop:  # Yield the decimal loop points (stop value excluded)
                yield start
                start += step

        # Case: decrement step ( < 0 )
        else:
            while start > stop:  # Yield the decimal loop points (stop value excluded)
                yield start
                start += step

        # Yield the stop value (inclusive)
        if stop_inclusive:
            yield stop

    except (ValueError, decimal.DecimalException) as ex:
        raise ValueError(f'{__name__}.range_decimal() error: {ex}')

这是使用小数的Python range() 等效函数。屈服值是精确的。


    Rangelow = 36
    Rangehigh = 37
    Delta = 0.1

    print("Celsius to Fahrenheit by", Delta)
    for i in range_decimal(Rangelow, Rangehigh, Delta, stop_inclusive=True):
        print(f'{i:.1f}               {i * 9 / 5 + 32}')
Celsius to Fahrenheit by 0.1
36.0               96.8
36.1               96.98
36.2               97.16
36.3               97.34
36.4               97.52
36.5               97.7
36.6               97.88
36.7               98.06
36.8               98.24
36.9               98.42
37.0               98.6
作者头像

这是一个 decimal_range 想法的实现,它涵盖了递增和递减,而无需转换为 decimal 类,也无需为 none 类型等进行大量验证和处理。

它还将返回停止值本身

def decimal_range(start, stop, increment):
    """
    Like built-in range, but works for floating point numbers
    """
    current = start

    while (start < stop and current < stop) 
          or (start > stop and current > stop) 
          or decimal_is_close(current, stop, increment / 4.0):

        # optional, but useful if you really need to guarantee the stop value itself
        # is returned and not something that is just really really close
        if decimal_is_close(current, stop, increment / 4.0):
            current = stop

        yield current
        current += increment

def decimal_is_close(value, target, what_is_close):
    return abs(value - target) < what_is_close