Jak miałbym wykonać math.ceil
tak, aby numer został przypisany do następnej najwyższej potęgi 10?
# 0.04 -> 0.1
# 0.7 -> 1
# 1.1 -> 10
# 90 -> 100
# ...
Moje obecne rozwiązanie to słownik, który sprawdza zakres liczby wejściowej, ale jest on zakodowany na stałe i wolałbym rozwiązanie jednoliniowe. Może brakuje mi tutaj prostej sztuczki matematycznej lub odpowiedniej funkcji numpy?
10
, będzie to wymagać czegoś nplog10
.Odpowiedzi:
Możesz używać
math.ceil
zmath.log10
tego robić:log10(n)
daje rozwiązaniex
które spełnia10 ** x == n
, więc jeśli zaokrąglisz w góręx
, daje wykładnik następnej najwyższej potęgi 10.Zauważ, że dla wartości,
n
którax
jest już liczbą całkowitą, „następną najwyższą potęgą 10” będzien
:źródło
10 ** math.ceil(math.log10(1)) == 1
Która nie jest „następną najwyższą mocą”Twój problem jest nieokreślony, musisz cofnąć się i zadać kilka pytań.
W innej odpowiedzi zaproponowano, aby wziąć logarytm, a następnie zaokrąglić w górę (funkcja pułapu), a następnie potęgować.
Niestety cierpi to na błędy zaokrąglania. Przede wszystkim n jest konwertowane z dowolnego typu danych, który ma, na liczbę zmiennoprzecinkową o podwójnej precyzji, potencjalnie wprowadzając błędy zaokrąglania, następnie logarytm jest obliczany, potencjalnie wprowadzając więcej błędów zaokrąglania zarówno w wewnętrznych obliczeniach, jak i w wyniku.
Jako taki nie zajęło mi długo znalezienie przykładu, w którym dał niepoprawny wynik.
Teoretycznie możliwe jest, że zawiodą w innym kierunku, choć wydaje się to znacznie trudniejsze do sprowokowania.
Dlatego dla solidnego rozwiązania dla liczb zmiennoprzecinkowych i liczb wewnętrznych musimy założyć, że wartość naszego logarytmu jest jedynie przybliżona i dlatego musimy przetestować kilka możliwości. Coś w stylu
Uważam, że ten kod powinien dawać poprawne wyniki dla wszystkich argumentów w rozsądnym zakresie wielkości rzeczywistych. Zepsuje się dla bardzo małej lub bardzo dużej liczby typów niecałkowitych i nie zmiennoprzecinkowych z powodu problemów z konwersją ich na zmiennoprzecinkowe. Python w szczególnych przypadkach argumentuje liczby całkowite dla funkcji log10, próbując zapobiec przepełnieniu, ale wciąż przy wystarczająco dużej liczbie całkowitej może być możliwe wymuszenie niepoprawnych wyników z powodu błędów zaokrąglania.
Aby przetestować dwie implementacje, użyłem następującego programu testowego.
Stwierdzono wiele błędów we wdrożeniu naiwnym, ale nie we ulepszonym.
źródło
round
zamiastmath.ceil
? Spowoduje to wprowadzenie wielu niepotrzebnych przypadków, w którychr < n
jest to prawdą, dlatego musi wykonać dodatkową pracę.Wygląda na to, że chcesz raczej najniższej następnej potęgi 10 ... Oto sposób korzystania z czystej matematyki i bez dziennika, ale rekurencja.
źródło
Może coś takiego? Jest tuż przy mojej głowie, ale zadziałało, gdy wypróbowałem kilka numerów w terminalu.
źródło
Spójrz na to!
Ten kod oparty na zasadzie mocy dziesięciu w
len( str( int( float_number ) ) )
.Istnieją 4 przypadki:
int( i ) > 1
.Float
Numer - przekształca sięint
następnie będzie ciągiemstr()
z nią, da namstring
zlength
co jesteśmy dokładnie szukać. Tak więc pierwsza część na wejściui > 1.0
- ma dziesięć10
mocy tej długości.i > 1.0
ii > 0.1
<=> odpowiednio10
i1
.i < 0.1
: tutaj dziesięć będzie w mocy ujemnej. Aby uzyskać pierwszy niezerowy element po przecinku, użyłem takiej konstrukcji("%.100f" % i ).replace('.','').index( k )
, w której k przebiega przez[1:10]
interwał. Następnie weź minimum listy wyników. I pomniejsz o jeden, to pierwsze zero, które należy policzyć. Również tutaj norma Pythonaindex()
może upaść, jeśli nie znajdzie się co najmniej jeden z niezerową elementu z[1:10]
przedziału, dlatego w końcu muszę „filtr” wystawianie przez występowania:if str( j ) in "%.100f" % i
. Ponadto, aby uzyskać głębszą precyzję -%.100f
mogą się różnić.źródło