Как перевести строковые значения Decimal в число?

Есть текстовый файл с данными такого вида:


    -7.271467826427747 17.84
    -7.238717596285217 17.83
    -7.203784017466519 17.82
    -7.171033787323988 17.81
    -7.138283557181459 17.80
    -7.103349978362760 17.79
    -7.068416399544062 17.78
    -7.033482820725363 17.77
    -6.998549241906665 17.76
    -6.961432314411798 17.75
    -6.924315386916930 17.74
    -6.889381808098232 17.73
    -6.852264880603365 17.72
    -6.812964604432329 17.71
    -6.775847676937462 17.70
    -6.738730749442595 17.69
    -6.699430473271558 17.68
    -6.660130197100525 17.67
    -6.618646572253319 17.66
    -6.577162947406114 17.65
    -6.537862671235079 17.64
    -6.496379046387874 17.63
    -6.452712072864502 17.62
    -6.409045099341129 17.61
    -6.365378125817755 17.60

Я пытаюсь перегнать этот файл в массив:

import numpy as np

_overall_survival = open('_overall_survival.txt').read().splitlines()
mas = np.array([line.split() for line in _overall_survival[0:]], float, order='F')

print(mas)

На выходе получаем:


    [[-39.16145859  81.01      ]
     [-39.81064093  81.02      ]
     [-40.02431799  81.03      ]
     ...
     [ -2.39123878  17.24      ]
     [ -2.45739627  17.23      ]
     [ -2.5248678   17.22      ]]

В принципе работает, но, float не обеспечивает точности передачи знаков после запятой, а это важно.

Я попробовал использовать Decimal:

from decimal import *
import numpy as np

_overall_survival = open('_overall_survival.txt').read().splitlines()
mas = np.array([line.split() for line in _overall_survival[0:]], Decimal, order='F')

print(mas)

На выходе получаем:


    [['-39.161458590547106' '81.01']
     ['-39.810640930261251' '81.02']
     ['-40.024317987368960' '81.03']
     ...
     ['-2.391238778978993' '17.24']
     ['-2.457396265486048' '17.23']
     ['-2.524867804437093' '17.22']]

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

Вопрос: как сохраняя точность Decimal, получить не строку, а число?

ДОПОЛНЕНИЕ:

Опираясь на советы Stanislav Volodarskiy, CrazyElf, Vitalizzare удалось собрать работоспособный прототип программы.

import tkinter as tk
import numpy as np
from tkinter import ttk

with open('_overall_survival.txt') as f:
    array = np.array([list(map(float, line.split())) for line in f])
    with ((np.printoptions(precision=15))):
        mas = array


# ENGINE
# region
def calc():
    with ((np.printoptions(precision=15))):
        result = float((-0.02144927 * float(entry_a.get())
                        ) + (-0.04948455 * float(entry_b.get())
                             ) + 0.50824824)

        row = mas[np.abs(mas[:, 0] - result).argmin()]
        min_row = float(mas[np.abs(mas[:, 0]).argmin()][0])
        max_row = float(mas[np.abs(mas[:, 0]).argmax()][0])

        if min_row >= result >= max_row:
            score['text'] = mas[np.where(mas == row)][1]
            info['text'] = (f'Расчет: {result}\n'
                            f'ТОЧНОГО СОВПАДЕНИЯ НЕТ!\n'
                            f'Ближайшее значение: '
                            f'{mas[np.where(mas == row)][0]}\n'
                            f'Связанное значение: '
                            f'{mas[np.where(mas == row)][1]}')
        elif result < max_row:
            score['text'] = mas[np.where(mas == row)][1]
            info['text'] = (f'Расчет: {result}\n'
                            f'СОВПАДЕНИЙ НЕТ!\n'
                            f'Расчетное время больше: '
                            f'{mas[np.where(mas == row)][1]}')
        elif result > max_row:
            score['text'] = mas[np.where(mas == row)][1]
            info['text'] = (f'Расчет: {result}\n'
                            f'СОВПАДЕНИЙ НЕТ!\n'
                            f'Расчетное время меньше: '
                            f'{mas[np.where(mas == row)][1]}')
        elif result in mas[:, 0]:
            score['text'] = mas[np.where(mas == row)][1]
            info['text'] = (f'Расчет: {result}\n'
                            f'ЕСТЬ СОВПАДЕНИЕ!\n'
                            f'Связанное значение: '
                            f'{mas[np.where(mas == row)][1]}')


def clear():
    entry_a.delete(0, 'end')
    entry_b.delete(0, 'end')
    # combobox.set('')
    score['text'] = ''
# endregion

# WINDOW
# region
app = tk.Tk()
app.title('FRM CLEAR')
width = 600
height = 350
x = int((app.winfo_screenwidth() / 2) - (width / 2))
y = int((app.winfo_screenheight() / 2) - (height / 2))
app.geometry(f'{width}x{height}+{x}+{y}')
app.resizable(width=False, height=False)
app['background'] = '#3d505a'
# endregion

# RESOURCES
# region
ttk.Style().configure('btn.TButton', background='#56676f')
ttk.Style().configure('frm_app.TFrame', background='#3d505a')
ttk.Style().configure('frm_content.TFrame', background='#56676f')

frm_app = ttk.Frame(app, style='frm_app.TFrame', padding=[20, 20])
frm_app.place(relheight=1, relwidth=1)

frm_content = ttk.Frame(frm_app, style='frm_content.TFrame', padding=[10, 10])
frm_content.place(relheight=0.5, relwidth=1)
# endregion


# UI
# region
entry_a = ttk.Entry(frm_content)
entry_a.place(x=5, y=10, height=25, width=40)

entry_b = ttk.Entry(frm_content)
entry_b.place(x=5, y=45, height=25, width=40)

score = ttk.Label(frm_content, text='', font='Tahoma 20 bold')
score.place(x=235, y=10, height=38, width=300)

info = ttk.Label(frm_content, text='', font='Tahoma 12', 
                 foreground='#ffffff', background='#56676f')
info.place(x=235, y=50, height=77, width=300)

tk.Button(app, text="Calc", command=calc
          ).place(x=470, y=305, height=25, width=50)
tk.Button(app, text="Clear", command=clear
          ).place(x=530, y=305, height=25, width=50)
# endregion
app.mainloop()

Насчет поэкспериментировать с Decimal, я сделаю такой вариант, но, поскольку в дальнейшем там происходят не столько вычисления, сколько поиск и сравнение с содержимым массива, разницы не будет (ну или она не будет влиять на результат сравнения).


Ответы (1 шт):

Автор решения: Stanislav Volodarskiy

NumPy не печатает все значащие цифры, его надо настроить: numpy.set_printoptions.

import numpy as np

with open('temp.txt') as f:
    a = np.array([
        list(map(float, line.split()))
        for line in f
    ])

with np.printoptions(precision=15):
    print(a)

Все цифры на месте:

$ python np-print.py
[[-7.271467826427747 17.84             ]
 [-7.238717596285217 17.83             ]
 [-7.203784017466519 17.82             ]
 [-7.171033787323988 17.81             ]
 [-7.138283557181459 17.8              ]]

Если всё-таки хотите работать с decimal.Decimal, то NumPy может ими манипулировать. Медленно, но может:

import decimal
import numpy as np

with open('temp.txt') as f:
    a = np.array([
        list(map(decimal.Decimal, line.split()))
        for line in f
    ])

print(a)
print(2 * a)
$ python np-decimal.py
[[Decimal('-7.271467826427747') Decimal('17.84')]
 [Decimal('-7.238717596285217') Decimal('17.83')]
 [Decimal('-7.203784017466519') Decimal('17.82')]
 [Decimal('-7.171033787323988') Decimal('17.81')]
 [Decimal('-7.138283557181459') Decimal('17.80')]]
[[Decimal('-14.542935652855494') Decimal('35.68')]
 [Decimal('-14.477435192570434') Decimal('35.66')]
 [Decimal('-14.407568034933038') Decimal('35.64')]
 [Decimal('-14.342067574647976') Decimal('35.62')]
 [Decimal('-14.276567114362918') Decimal('35.60')]]
→ Ссылка