Има ли начин в Python да се преброят значимите цифри в double/float/etc? Не виждам лесен начин да направя това, но бих очаквал да е в библиотеката.
Благодаря предварително.
Има ли начин в Python да се преброят значимите цифри в double/float/etc? Не виждам лесен начин да направя това, но бих очаквал да е в библиотеката.
Благодаря предварително.
Не. Значимите цифри просто не са толкова голяма работа и получават малко поддръжка в компютърните езици. Хората, които правят реални изчисления, се нуждаят от ленти за грешки, които имат много по-голяма точност - реалните измервания казват много точни неща като „това е 0,11 ± 0,03 mm“, вместо да казват едно от по-малко точните твърдения „това е 0,1 mm“ или „това е 0,11 mm ”, което ви кара да изберете степен на десет, дори ако вашата неточност всъщност не попада на степен на десет.
Може да се интересувате от библиотека с плаваща запетая с произволна точност като тази:
http://code.google.com/p/mpmath/
Намерих решение на тази публикация в друг въпрос:
Идеята тук е, че предавате float като String на методите и след това методът използва регулярни изрази, за да преброи броя на значимите цифри чрез разделяне на низове, където е "e"
(за низ с float в научен формат) и където е точката ( за нормални плаващи низове).
Изглежда, че работи добре до 8 значещи цифри, но поведението не е гарантирано след 9-та.
Все пак вярвам, че това е по-добро от
„Значимите цифри просто не са толкова голяма работа и получават малка поддръжка в компютърните езици“
отговор. Може да не е лесно, но определено можете да го направите, дори и не перфектно.
Компютрите просто не работят по този начин, поне освен ако не са програмирани да го правят. Предположението е, че числото, което им давате, е точно. Ако създадете числото 2/3 като 0,6666666666666667, тогава всички операции го третират като точно това. Тази грешка в най-малката цифра може в крайна сметка да се разпространи до по-големи грешки при по-късни изчисления, но това е нещо, с което добрият код трябва да се справи, като използва алгоритми, които минимизират тези проблеми, когато е възможно.
Както казах обаче, компютрите правят това, което им се каже. Така че има написани пакети, които използват така наречената интервална аритметика. Тогава едно число може да бъде описано като интервал, така че можем да създадем 2/3 като интервал [0.6666666666666666,0.6666666666666667]. Можем да оперираме с интервали, като добавяме, изваждаме, умножаваме и т.н. При тези операции ширините на интервалите често се разширяват, докато работим с тях.
Факт е обаче, че дори и да използвате инструменти за интервална аритметика, ВИЕ трябва да знаете в началото броя на значимите цифри във вашите числа. Ако създадете число като 2.2, съхранявайки го като двойно, тогава компютърът всъщност ще се опита да съхрани числото като 2.200000000000000 и ще приеме, че всички цифри са точно правилни. Всъщност, разбира се, тъй като се използва аритметика с плаваща запетая, числото всъщност ще се съхранява вътрешно като двоично число. Така че 2.2 вероятно ще бъде ефективно съхранено като число:
2.20000000000000017763568394002504646778106689453125
защото повечето десетични дробни числа не могат да бъдат представени точно в двоична форма. Отново трябва да се внимава във всеки софтуер, но винаги и от лицето, което използва тези инструменти, за да разбере какво наистина означават техните числа.
Тази последна точка е важна. Много хора приемат числата, генерирани от компютър, като истина, предадена от компютърния бог върху каменна плоча. Ако компютърът отпечата 1.4523656535725, те вярват на всяка цифра от това, което виждат. Всъщност тук трябва да се приложи здрав разум, за да се знае, че може би това число е генерирано от данни, които имат само 3 значими цифри, така че можете да изберете да разчитате само на първите няколко значими цифри от това число. И разбира се, това е причината да ви учат на тази концепция в училище, да знаете на какво да вярвате и на какво не. Не забравяйте обаче - компютрите като цяло ще бъдат безкрайно доверчиви. Вие трябва да приложите филтъра.
Вградената Decimal библиотека може да помогне доста добре с това, тъй като заобикаля опасенията с използването на хардуерно базирани числа с плаваща запетая. Има вътрешно представяне, което съдържа само значимите цифри и експонентата. Така че можете да използвате това, за да преброите значими цифри като това:
from decimal import Decimal
def count_sigfigs(numstr):
return len(Decimal(numstr).normalize().as_tuple().digits)
Това работи доста добре за много примери, като тези (от този свързан въпрос). Имайте предвид, че трябва да въведете числата като низове, за да работи правилно. Използването на float би го объркало поради тяхното хардуерно представяне.
tests = [('2', 1),
('1234', 4),
('2.34', 3),
('3000', 1),
('0.0034', 2),
('120.5e50', 4),
('1120.5e+50', 5),
('120.52e-50', 5)]
for num, expected in tests:
print(count_sigfigs(num) == expected)
Което дава:
True
True
True
True
True
True
True
True
За съжаление това не работи съвсем с числа като 1000, които имат 4 sigfigs. Това просто дава 1. Така че ще има нужда от подобрение, за да обхване всички случаи. Също така дава 1 за 0, въпреки че обикновено трябва да дава 0.
Ако извадите normalize
, тогава той работи за 1.000
, но не и за 3000 (пише 4, а не 1).