簡體   English   中英

從十進制中刪除尾隨零

[英]drop trailing zeros from decimal

我有一長串小數,我必須根據某些條件調整 10、100、1000、..... 1000000 的因子。 當我將它們相乘時,有時我想去掉一個無用的尾隨零(盡管並非總是如此)。 例如...

from decimal import Decimal

# outputs 25.0,  PROBLEM!  I would like it to output 25
print Decimal('2.5') * 10

# outputs 2567.8000, PROBLEM!  I would like it to output 2567.8
print Decimal('2.5678') * 1000

是否有一個函數可以告訴十進制對象刪除這些無關緊要的零? 我能想到的唯一方法是轉換為字符串並使用正則表達式替換它們。

可能應該提到我正在使用 python 2.6.5

編輯 senderle 的好回答讓我意識到我偶爾會得到一個像 250.0 這樣的數字,當歸一化時會產生 2.5E+2。 我想在這些情況下,我可以嘗試將它們整理出來並轉換為 int

您可以使用normalize方法去除額外的精度。

>>> print decimal.Decimal('5.500')
5.500
>>> print decimal.Decimal('5.500').normalize()
5.5

為避免在小數點左側去除零,您可以這樣做:

def normalize_fraction(d):
    normalized = d.normalize()
    sign, digits, exponent = normalized.as_tuple()
    if exponent > 0:
        return decimal.Decimal((sign, digits + (0,) * exponent, 0))
    else:
        return normalized

或者更緊湊,采用quantize的建議由user7116

def normalize_fraction(d):
    normalized = d.normalize()
    sign, digit, exponent = normalized.as_tuple()
    return normalized if exponent <= 0 else normalized.quantize(1)

您也可以使用to_integral()如此處所示但我認為以這種方式使用as_tuple更能自我記錄。

我在幾個案例中測試了這兩者; 如果您發現一些不起作用的東西,請發表評論。

>>> normalize_fraction(decimal.Decimal('55.5'))
Decimal('55.5')
>>> normalize_fraction(decimal.Decimal('55.500'))
Decimal('55.5')
>>> normalize_fraction(decimal.Decimal('55500'))
Decimal('55500')
>>> normalize_fraction(decimal.Decimal('555E2'))
Decimal('55500')

可能有更好的方法來做到這一點,但您可以使用.rstrip('0').rstrip('.')來實現您想要的結果。

以您的數字為例:

>>> s = str(Decimal('2.5') * 10)
>>> print s.rstrip('0').rstrip('.') if '.' in s else s
25
>>> s = str(Decimal('2.5678') * 1000)
>>> print s.rstrip('0').rstrip('.') if '.' in s else s
2567.8

這是 gerrit 在評論中指出的問題的解決方法:

>>> s = str(Decimal('1500'))
>>> print s.rstrip('0').rstrip('.') if '.' in s else s
1500

來自文檔中Decimal常見問題解答

>>> def remove_exponent(d):
...     return d.quantize(Decimal(1)) if d == d.to_integral() else d.normalize()

>>> remove_exponent(Decimal('5.00'))
Decimal('5')

>>> remove_exponent(Decimal('5.500'))
Decimal('5.5')

>>> remove_exponent(Decimal('5E+3'))
Decimal('5000')

常見問題解答( https://docs.python.org/2/library/decimal.html#decimal-faq )中提到了答案,但沒有解釋。

要刪除分數部分的尾隨零,您應該使用normalize

>>> Decimal('100.2000').normalize()
Decimal('100.2')
>> Decimal('0.2000').normalize()
Decimal('0.2')

但這對於尖銳部分帶有前導零的數字的工作方式不同:

>>> Decimal('100.0000').normalize()
Decimal('1E+2')

在這種情況下,我們應該使用“to_integral”:

>>> Decimal('100.000').to_integral()
Decimal('100')

所以我們可以檢查是否有小數部分:

>>> Decimal('100.2000') == Decimal('100.2000').to_integral()
False
>>> Decimal('100.0000') == Decimal('100.0000').to_integral()
True

然后使用適當的方法:

def remove_exponent(num):
    return num.to_integral() if num == num.to_integral() else num.normalize()

嘗試一下:

>>> remove_exponent(Decimal('100.2000'))
Decimal('100.2')
>>> remove_exponent(Decimal('100.0000'))
Decimal('100')
>>> remove_exponent(Decimal('0.2000'))
Decimal('0.2')

現在我們完成了。

使用格式說明符%g 它似乎刪除了尾隨零。

>>> "%g" % (Decimal('2.5') * 10)
'25'
>>> "%g" % (Decimal('2.5678') * 1000)
'2567.8'

它也可以在沒有Decimal函數的情況下工作

>>> "%g" % (2.5 * 10)
'25'
>>> "%g" % (2.5678 * 1000)
'2567.8'

我最終這樣做了:

import decimal

def dropzeros(number):
    mynum = decimal.Decimal(number).normalize()
    # e.g 22000 --> Decimal('2.2E+4')
    return mynum.__trunc__() if not mynum % 1 else float(mynum)

print dropzeros(22000.000)
22000
print dropzeros(2567.8000)
2567.8

注意:將返回值轉換為字符串會將您限制為 12 位有效數字

A-IV 答案的略微修改版本

注意Decimal('0.99999999999999999999999999995').normalize()將四舍五入為Decimal('1')

def trailing(s: str, char="0"):
    return len(s) - len(s.rstrip(char))

def decimal_to_str(value: decimal.Decimal):
    """Convert decimal to str

    * Uses exponential notation when there are more than 4 trailing zeros
    * Handles decimal.InvalidOperation
    """
    # to_integral_value() removes decimals
    if value == value.to_integral_value():
        try:
            value = value.quantize(decimal.Decimal(1))
        except decimal.InvalidOperation:
            pass
        uncast = str(value)
        # use exponential notation if there are more that 4 zeros
        return str(value.normalize()) if trailing(uncast) > 4 else uncast
    else:
        # normalize values with decimal places
        return str(value.normalize())
        # or str(value).rstrip('0') if rounding edgecases are a concern

這應該有效:

'{:f}'.format(decimal.Decimal('2.5') * 10).rstrip('0').rstrip('.')

我正在處理json字典中的值(由API返回)。 以上所有都沒有幫助我,所以我由自己的幫助器功能構造了。 它會截斷所有尾隨的零。

我希望它可以幫助某個人

def remove_zeros(num):
    nums = list(num)
    indexes = (list(reversed(range(len(nums)))))
    for i in indexes:
        if nums[i] == '0':
            del nums[-1]
        else:
            break
    return "".join(nums)

num = "0.000000363000"
print(remove_zeros(num))

版畫:

0.000000363

只是為了展示不同的可能性,我使用to_tuple()來實現相同的結果。

def my_normalize(dec):
    """
    >>> my_normalize(Decimal("12.500"))
    Decimal('12.5')
    >>> my_normalize(Decimal("-0.12500"))
    Decimal('-0.125')
    >>> my_normalize(Decimal("0.125"))
    Decimal('0.125')
    >>> my_normalize(Decimal("0.00125"))
    Decimal('0.00125')
    >>> my_normalize(Decimal("125.00"))
    Decimal('125')
    >>> my_normalize(Decimal("12500"))
    Decimal('12500')
    >>> my_normalize(Decimal("0.000"))
    Decimal('0')
    """
    if dec is None:
        return None

    sign, digs, exp = dec.as_tuple()
    for i in list(reversed(digs)):
        if exp >= 0 or i != 0:
            break
        exp += 1
        digs = digs[:-1]

    if not digs and exp < 0:
        exp = 0

    return Decimal((sign, digs, exp))

您可以使用 %g 來實現此目的:

'%g'%(3.140)

用 Python 嗎? 2.6: '{0:g}'.format(3.140)

為什么不使用 10 的倍數中的模數 10 來檢查是否有余數? 沒有余數意味着你可以強制 int()

if (x * 10) % 10 == 0:
    x = int(x)

x = 2/1
輸出: 2

x = 3/2
輸出: 1.5

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM