Найти наименьшую значащую цифру в двойнике в Python

У меня есть много финансовых данных, хранящихся как удвоения с плавающей запятой, и я пытаюсь найти наименее значащую цифру, чтобы преобразовать данные в целые числа с показателем степени.

Все данные конечны, например. 1234,23 или 0,0001234, но поскольку он хранится в двойном формате, он может быть 123,23000000001 или 0,00012339999999 и т. д.

Есть ли простой или правильный подход к этому, или мне просто придется все испортить?

Я не думаю, что проблема четко определена, потому что может быть несколько чисел, которые заканчиваются одними и теми же удвоениями, поэтому информация уже потеряна. Финансовые данные никогда не должны храниться в формате с плавающей запятой.

wim 02.04.2022 18:12

В этом случае избегайте плавающей запятой. Использовать decimal

trincot 02.04.2022 18:12
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
2
64
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

У вас есть несколько вариантов,

Во-первых и наиболее предпочтительно, используйте стандартную библиотеку Decimal, а не встроенную float

Это исправляет большинство ошибок, связанных с поплавками, но не печально известную 0.1 + 0.2 = 0.3...4

from decimal import Demical

print(0.1 + 0.2)  # 0.30000000000000004
print(Decimal(0.1) + Decimal(0.2))  # 0.3000000000000000166533453694

Альтернативным вариантом, если это невозможно, является установка допустимого количества повторяющихся цифр после запятой.

Например:

import re

repeated_digit_tolerance = 8  # Change to an appropriate value for your dataset
repeated_digit_pattern = re.compile(r"(.)\1{2,}")

def longest_repeated_digit_re(s: str):
    match = repeated_digit_pattern.search(s)

    string = match.string
    span = match.span()
    substr_len = span[1] - span[0]

    return substr_len, string

def fix_rounding(num: float) -> float:
    num_str = str(num)
    pre_dp = num_str[:num_str.index(".")]
    post_dp = num_str[num_str.index(".") + 1:]

    repetition_length, string = longest_repeated_digit_re(post_dp)

    if repetition_length > repeated_digit_tolerance:
        shortened_string = string[:repeated_digit_tolerance-1]

    return float(".".join([pre_dp, shortened_string]))

print(0.1 + 0.2) # 0.30000000000000004
print(0.2 + 0.4) # 0.6000000000000001

print(fix_rounding(0.1 + 0.2))  # 0.3
print(fix_rounding(0.2 + 0.4))  # 0.6

Это прекрасно функционирующий код, но Decimal практически всегда лучший вариант из двух, даже если он не будет работать 0.1 + 0.2 правильно.

Вот моя неудача с использованием строк. На данный момент он работает адекватно тому, что мне нужно, но я его полностью не тестировал.

print (int_sci_notation(0.1+0.2)) вернет кортеж (3,-1)

def int_sci_notation(decimal_value):
    #decimal value is finite value stored in double precision
    #convert to scientific string (cannot prevent E notation so force all numbers to E notation)
    tostr = format(decimal_value, ".14E")
    #get exponent from string
    if tostr[-3] == '-':
        exp = -int(tostr[-2:])
    else:
        exp = int(tostr[-2:])
    #get significant figures as an integer
    frac = tostr[1:-4].strip('0')
    sf = tostr[0]+frac[1:]
    #return the integer 'mantissa' and the exponent
    return int(sf), -int(len(sf)-1-exp)

Другие вопросы по теме