如何限制浮点数的长度而不仅仅是小数?

时间:2018-02-02 01:25:02

标签: python

我正在编写一个脚本,需要输出由长度而不仅仅是小数位确定的精度数字。假设我想要最多7位小数,但7位以上的整数都可以,但如果总位数为7或更高,它们就不能有小数位数。

所以规则是:

- If a float has more than 7 digits of whole numbers, it loses it's decimals
- If a float has less than 7 digits of whole numbers, it gets a length of 7 total digits including decimals
- If a floats has no digits of whole numbers, it keeps 7 decimals

例如:

a = 10000.02
b = 1.000002
c = 100000000000

都是正确的。

如何处理此格式的数字(所有float)?

例如:

d = 892432589.54680
e = 382.39810758264057251
f = 452545871.1643548
g = 10254.968743541742
h = 165783438364325.126

我正在考虑以下几点:

length_of_number = len(str(x))
    if length_of_number > 7:
        x.round(0)
    else:
        x.round(7 - length_of_number)

然后我遇到了像

这样的情况
x= 0.5313231568943218748

因为整个float超过7位数。

怎么办?

编辑问题示例:

12345678 is ok
1234567.1 is ok (but 1234567.12 not)
1.12345678 would become 1.123456

5 个答案:

答案 0 :(得分:0)

我真的没有得到你想要的东西,但也许这对你有帮助吗?

round(num_here, 7)

来自文档:

  

返回小数点后舍入到ndigits精度的数字。如果省略ndigits或者为None,则返回其输入的最接近的整数。

     

对于支持round()的内置类型,值将四舍五入为函数减去ndigits的最接近的10的倍数;如果两个倍数相等,则向均匀选择进行舍入(例如,round(0.5)round(-0.5)都为0,round(1.5)为2)。任何整数值对ndigits(正数,零或负数)有效。如果使用一个参数调用,则返回值为整数,否则与数字类型相同。

     

对于一般的Python对象编号,round(number, ndigits)委托给number.__round__(ndigits)

     
    

注意: round()对于浮点数的行为可能会令人惊讶:例如,round(2.675, 2)会提供2.67而不是预期的2.68。这不是一个错误:这是因为大多数小数部分不能完全表示为浮点数。请参阅Floating Point Arithmetic: Issues and Limitations for more information

  

答案 1 :(得分:0)

我认为您所询问的内容可以通过如何确定您的长度以及查找字符串中是否有小数来解决。例如,如果你说

>>>a = 1325.6326
>>>len(str(a).split(".")[0])
4

这将为您提供小数点左侧所有数字的长度。

>>>b = '.' in str(a)
>>>print(b)
True

这将告诉您数字中是否有小数位。

答案 2 :(得分:0)

def truncate(n):
    s = str(n)
    is_decimal = '.' in s
    if len(s) <= 7 + is_decimal:
        return s
    if not is_decimal:
        return s
    fore, aft = s.split('.', 1)
    if len(fore) >= 7:
        return fore
    if n < 1:
        return '{:.7f}'.format(n)
    return f'{{:.{7-len(fore)}f}}'.format(n)

这是一个版本,使用字符串格式来截断小数。事实证明,字符串格式实际上是圆形,而不是丢弃字符,因此字符串切片可能更适合您

def truncate(n):
    s = str(n)
    is_decimal = '.' in s
    if len(s) <= 7 + is_decimal:
        return s
    if not is_decimal:
        return s
    fore, aft = s.split('.', 1)
    if len(fore) >= 7:
        return fore
    if n < 1:
        return '.' + aft[:7]
    return '{}.{}'.format(fore, aft[:7-len(fore)])

答案 3 :(得分:0)

我稍微更改了您的代码并将其转换为一个函数,以便于测试。

num = [892432589.54680,
  382.39810758264057251,
  452545871.1643548,
  10254.968743541742,
  165783438364325.126,
  0.5313231568943218748]

def trunc_num(x):
  num_int = int(x)
  length_of_number = len(str(num_int))
  if length_of_number >= 7:
    return num_int
  else:
    return round(x, 7 - length_of_number)

for n in num:
  print(trunc_num(n))

通过将数字更改为int,小数被删除,我们可以检查数字的长度,但不包括小数。如果int大于7位数,我们只会返回int,否则我们会按照您之前尝试的方式对其进行舍入。

输出

892432589
382.3981
452545871
10254.97
165783438364325
0.531323

如果您需要考虑负数,则可以在将其转换为字符串后添加lstrip

length_of_number = len(str(num_int).lstrip('-'))

答案 4 :(得分:0)

这是一个使用字符串切片的超简单版本:

def seven(x):
    ret = lambda x: float(x) if '.' in str(x) else int(x)
    return ret(str(x)[:max(str(x).find('.'), 8 + ('-' in str(x)))].strip('.'))

输出:

<class 'int'>           892432590
<class 'int'>          -892432590
<class 'float'>          382.3981
<class 'float'>         -382.3981
<class 'int'>           452545871
<class 'int'>          -452545871
<class 'float'>          10254.97
<class 'float'>         -10254.97
<class 'int'>     165783438364325
<class 'int'>    -165783438364325
<class 'float'>          0.531323
<class 'float'>         -0.531323

使用str.format()的替代方案:

def seven(x):
    ret = lambda x: float(x) if '.' in x else int(x)
    return ret('{:.{cutoff}f}'.format(x, cutoff=7 - min(str(x).find('.') - ('-' in str(x)), 7)))