Difference of decimal numbers with another base - python

I am using Python. I have several pairs of numbers and I want to find their difference, but their base is on 42. For example,
5.39->5.40->5.41->5.42->6.00
So, 10.38 with 10.24 has 0.14, but 10.41 with 11.02 has 0.03
Is there any way to do this with Python? The only way I can imagine is to take several IF for every case.
Example of my data:
[3.08,3.15] --> 0.07
[4.39,5.10] --> 0.13
[13.00,14.12] --> 1.12
[40.42,41.01] --> 0.02

Like this? Subtracts A from B using 0.42 as cap for decimal part.
base = 42
a = (5,10)
b = (4,39)
if a > b:
b, a = a, b
overflow = int(b[1] < a[1])
c = (b[0]-a[0]-overflow, b[1]+base*overflow-a[1])
print(c)
Question is not very clear. Also I used tuples to avoid parsing.
Edit: added the if guard

This might be overkill, but...
digits = '0123456789abcdefghijklmnopqrstuvwxyzABCDEF'
assert len(digits) == 42
def base(n, b=2, digits=digits):
if n < 0:
raise ValueError("no negative numbers")
if n < b:
return digits[n]
res = []
q = n
while q:
q, r = divmod(q, b)
res.append(digits[r])
return ''.join(reversed(res))
def debase(s, base=2, digits=digits):
if not (2 <= base <= len(digits)):
raise ValueError("base must be >= 2 and <= %d" % len(digits))
res = 0
for i, v in enumerate(reversed(s)):
digit = digits.index(v)
res += digit * (base ** i)
return res
class Val(object):
def __init__(self, a, b):
self.a = a
self.b = base(b, 42)
def __sub__(self, other):
a = self.a - other.a
b = debase(self.b, 42) - debase(other.b, 42)
if b < 0:
b += 42
a -= 1
return Val(a, b)
def __repr__(self):
return "Val({a}, {b})".format(a=self.a, b=debase(self.b, 42))
def __str__(self):
return "%d.%02d" % (self.a, debase(self.b, 42))
print Val(4,20) - Val(4,10)
# 0.10
print Val(11,2) - Val(10,41)
# 0.03

I would have suggested simply setting the base parameter in int, but that only applies for numbers n in [2, 36]. Instead you can convert to and from any base with something like:
def frombase(numbers, n):
return sum(float(a)*n**i for i, a in izip(count(len(numbers)-1, -1), numbers))
def tobase(number, n):
numbers = []
while number:
numbers.append(int(number % n))
number = int(number / n)
return numbers
You could then produce the result per pair by doing:
converted = map(lambda x: frombase(str(x).split('.'), 42), numbers)
print('.'.join(tobase(abs(converted[1] - converted[0]))))
I'll leave it to you to generalize this into any set of symbols --> any other set of symbols.

First of all, there cant be an element 5.42 with base 42, i think the base should be 43.
I think this is it you want
a=11.02
b=10.41
base=43
def diff(a,b,base):
x=int(a)*base+int(round((a%1)*100))
y=int(b)*base+int(round((b%1)*100))
print x
print y
return (x-y)/base+((x-y)%base)/100.0
c=diff(a,b,base)
print c

Related

How do I go about coding a custom function (without using any library) which returns the log of a number in python [duplicate]

I need to generate the result of the log.
I know that:
Then I made my code:
def log(x, base):
log_b = 2
while x != int(round(base ** log_b)):
log_b += 0.01
print(log_b)
return int(round(log_b))
But it works very slowly. Can I use other method?
One other thing you might want to consider is using the Taylor series of the natural logarithm:
Once you've approximated the natural log using a number of terms from this series, it is easy to change base:
EDIT: Here's another useful identity:
Using this, we could write something along the lines of
def ln(x):
n = 1000.0
return n * ((x ** (1/n)) - 1)
Testing it out, we have:
print ln(math.e), math.log(math.e)
print ln(0.5), math.log(0.5)
print ln(100.0), math.log(100.0)
Output:
1.00050016671 1.0
-0.692907009547 -0.69314718056
4.6157902784 4.60517018599
This shows our value compared to the math.log value (separated by a space) and, as you can see, we're pretty accurate. You'll probably start to lose some accuracy as you get very large (e.g. ln(10000) will be about 0.4 greater than it should), but you can always increase n if you need to.
I used recursion:
def myLog(x, b):
if x < b:
return 0
return 1 + myLog(x/b, b)
You can use binary search for that.
You can get more information on binary search on Wikipedia:
Binary search;
Doubling search.
# search for log_base(x) in range [mn, mx] using binary search
def log_in_range(x, base, mn, mx):
if (mn <= mx):
med = (mn + mx) / 2.0
y = base ** med
if abs(y - x) < 0.00001: # or if math.isclose(x, y): https://docs.python.org/3/library/math.html#math.isclose
return med
elif x > y:
return log_in_range(x, base, med, mx)
elif x < y:
return log_in_range(x, base, mn, med)
return 0
# determine range using doubling search, then call log_in_range
def log(x, base):
if base <= 0 or base == 1 or x <= 0:
raise ValueError('math domain error')
elif 0 < base < 1:
return -log(x, 1/base)
elif 1 <= x and 1 < base:
mx = 1
y = base
while y < x:
y *= y
mx *= 2
return log_in_range(x, base, 0, mx)
elif 0 <= x < 1 and 1 < base:
mn = -1
y = 1/base
while y > x:
y = y ** 0.5
mn *= 2
return log_in_range(x, base, mn, 0)
import math
try :
number_and_base = input() ##input the values for number and base
##assigning those values for the variables
number = int(number_and_base.split()[0])
base = int(number_and_base.split()[1])
##exception handling
except ValueError :
print ("Invalid input...!")
##program
else:
n1 = 1 ##taking an initial value to iterate
while(number >= int(round(base**(n1),0))) : ##finding the most similer value to the number given, varying the vlaue of the power
n1 += 0.000001 ##increasing the initial value bit by bit
n2 = n1-0.0001
if abs(number-base**(n2)) < abs(base**(n1)-number) :
n = n2
else :
n = n1
print(math.floor(n)) ##output value
Comparison:-
This is how your log works:-
def your_log(x, base):
log_b = 2
while x != int(round(base ** log_b)):
log_b += 0.01
#print log_b
return int(round(log_b))
print your_log(16, 2)
# %timeit %run your_log.py
# 1000 loops, best of 3: 579 us per loop
This is my proposed improvement:-
def my_log(x, base):
count = -1
while x > 0:
x /= base
count += 1
if x == 0:
return count
print my_log(16, 2)
# %timeit %run my_log.py
# 1000 loops, best of 3: 321 us per loop
which is faster, using the %timeit magic function in iPython to time the execution for comparison.
It will be long process since it goes in a loop. Therefore,
def log(x,base):
result = ln(x)/ln(base)
return result
def ln(x):
val = x
return 99999999*(x**(1/99999999)-1)
log(8,3)
Values are nearly equal but not exact.

RSA Cryptography shows wrong result for large prime numbers

I implemented a RSA Cryptography program, using python, and it works perfectly using prime numbers with aproximally 10 digits. But when I use numbers with 25 digits or more, for example, it does not work.
It worked with the following keys:
p = 2324731
q = 186647
e = 433899328297
n = 433904066957
It not worked with:
p = 3673864730662357928718503
q = 2127738717256957618781057
e = 7817024229395103552360986476332293342120062315901
n = 7817024229395103552360993847944520620136941797671
here's the code:
inverse (d key):
#classmethod
def __linearOperation(cls, a, b, mdc, i):
t = -int(a / b)
r = a % b
mdc.append([1, a, t, b])
if r == 1:
return mdc
inverseLine = cls.__linearOperation(b, r, mdc, i + 1)
s = inverseLine[i][0]
t = inverseLine[i][2]
inverseLine[i - 1][0] *= t
inverseLine[i - 1][2] *= t
inverseLine[i - 1][2] += s
inverseLine.remove(inverseLine[i])
return inverseLine
def __inverse(self, e, φ):
inverseLine = self.__linearOperation(e, φ, [], 1)
inverse = inverseLine[0][0]
if inverse < 0:
return inverse + φ
if inverse > φ:
return inverse % φ
else:
return inverse
Modular Exponentiation:
#staticmethod
def __QuickMod(base, exp, n):
result = 1
while exp > 0:
if exp & 1:
result = (result * base) % n
base = (base ** 2) % n
exp = exp >> 1
return result
encrypt/decrypt:
def encryptChar(self, n: int, e: int, M: int) -> int:
C = self.__QuickMod(M, e, n) # C = M^e mod n
return C
def decryptChar(self, p: int, q: int, e: int, C: int) -> int:
d = self.__inverse(e, (p - 1) * (q - 1))
M = self.__QuickMod(C, d, p * q) # M = C^d mod n
return M
By trying to encrypt the number 109 ("m" char in ascII), the encryptChar function returns 6825028446539883496812231478440519650519629664279.
By trying to decrypt the number above the decryptChar function should returns the number 109 back. But that's not what happens.
In my conception, by using python we do not have number size restriction.
Is there something i'm not seeing? Thank you for your help.
The problem is in my inverse algorithm. I'll try to re-implement it. But using pow() function with -1 as expoent works.

How to add 2 singly-linked lists together?

I am trying to write a Python function that adds two linked lists together. Each node contains one digit of a potentially large integer, with the least-significant digit coming first
Ex Function: add_linked_list_integers(a, b) - where a and b are singly-linked list whose nodes each contain one digit of a positive integer.
Ex Problem: 617 + 295 = 912 would be represented in linked-lists as (7->1->6) + (5->9->2) = (2->1->9).
I am provided with a basic ListNode class, and sample functions to print and create a linked-list of integers.
class ListNode:
'''Simple node for singly-linked list with _value and _next fields'''
def __init__(self, value, next=None):
'''Create a new node, with _value field and optional _next node pointer'''
self._value = value
self._next = next
def print_helper(l):
'''Prints the value of the integer represented by the linked-list l, without trailing carriage return'''
if l:
if (l._value < 0) or (l._value > 9):
raise Exception('digit out of range')
print_helper(l._next)
print(l._value, end="")
def print_linked_list_integer(l):
'''Prints the value of the integer represented by the linked-list l, with trailing carriage return'''
print_helper(l)
print()
def create_linked_list_integer(i):
'''Returns the linked-list representation of the integer i, least-significant digit first'''
result = ListNode(i % 10)
if i >= 10:
result._next = create_linked_list_integer(i // 10)
return result
def add_linked_list_integers(a, b):
'''Return the sum of two integers represented as linked lists
Currently my function looks like this:
def add_linked_list_integers(a, b):
'''Return the sum of two integers represented as linked lists'''
answer = ListNode()
if a == None:
return b
elif b == None:
return a
carry = 0
result = (a.data + b.data + carry)
if result > 9:
result = result - 10
carry = 1
answer.push(result)
return answer
def add_linked_list_integers(a, b):
'''Return the sum of two integers represented as linked lists'''
pre_head = ListNode(-1)
carry = 0
head = pre_head
while a is not None and b is not None:
digit = (a._value + b._value + carry) % 10
carry = (a._value + b._value + carry) // 10
head._next = ListNode(digit)
head = head._next
a = a._next
b = b._next
while a is not None:
digit = (a._value + carry) % 10
carry = (a._value + carry) // 10
head._next = ListNode(digit)
head = head._next
a = a._next
while b is not None:
digit = (b._value + carry) % 10
carry = (b._value + carry) // 10
head._next = ListNode(digit)
head = head._next
b = b._next
if carry != 0:
head._next = ListNode(carry)
return pre_head._next
This is what I would do
Just perform the equivalent of base-10 addition. This means looping over the digits!
from itertools import zip_longest
def add_linked_list_integers(xs, ys):
carry = 0
result = []
for x, y in zip_longest(xs, ys, fillvalue=0):
s = x + y + carry
carry = s // 10
result.append(s % 10)
if carry > 0:
result.append(carry)
return result
Example runs:
>>> add_linked_list_integers([7, 1, 6], [5, 9, 2])
[2, 1, 9]
>>> to_list = lambda y: [int(x) for x in reversed(str(y))]
>>> to_int = lambda xs: int(''.join(str(x) for x in xs)[::-1])
>>> a, b = 3192097619, 999999998472534892
>>> a + b
1000000001664632511
>>> to_int(add_linked_list_integers(to_list(a), to_list(b)))
1000000001664632511

GCD implementation in python

I am solving this problem in SPOJ and it states that :
Problem statement is simple. Given A and B you need to calculate
S(A,B) .
Here, f(n)=n, if n is square free otherwise 0. Also f(1)=1.
Input
The first line contains one integer T - denoting the number of test
cases.
T lines follow each containing two integers A,B.
Output
For each testcase output the value of S(A,B) mod 1000000007 in a
single line.
Constraints
`T <= 1000
1 <= A,B <= 1000000`
Example
Input:
3
42 18
35 1
20 25
Output:
306395
630
128819
I wrote this code for this problem (if I got the the problem right) :
def gcd(a,b): #gcd(a,b)
if b==0:
return a
else:
return gcd(b,a%b)
# print gcd(42,18)
import math
def issquarefree(n): #sqare free number check
i=2
s=i*i
if (n==1 or n==2) or n==3:
return True
while s<=n:
if n%s==0:
i=-1
break
else:
i+=1
s=i*i
if i==-1:return False
else:
return True
for i in range(int(raw_input())): #main program
a,b=map(int,raw_input().split())
g=gcd(a,b)
sa=(a*(a+1))/2 #see below
sb=(b*(b+1))/2 #see below
gc=issquarefree(g)
s=0
if gc== False:
print 0
elif gc==True:
s+=sa*sb*g
print s%1000000007
here I found that so applying this to the problem # S(A,B) I wrote this as (multiplication of sum of first A and B numbers ) multiplied by f(n) which is gcd(a,b) or 0.
But I am not getting the expected output to this problem so is my code wrong or I got the problem wrong
my output vs expected
3
35 1
42 18
20 25
630 630
926478 306395
341250 128819
Writing out the G(a, b) = f(gcd(a, b)) (so that you can use the cited formula) is incorrect since the function is not constant. The proper solution is this:
for i in range(int(raw_input())):
A, B = map(int, raw_input().split())
# proper algorithm
s = 0
for a in xrange(1, A):
for b in xrange(1, B):
s += a * b * G(a, b)
print s % 1000000007
You obviously have to implement G function properly (as returning 0 or gcd(a, b)).
Careful analysis of G might give some optimization insight but it is definitely not a trivial one if any.
Here is a simple optimization:
import fractions
DIVISOR = 1000000007
def is_not_square_free(a):
counter = 1
factor = 1
while factor < a:
counter += 1
factor = counter * counter
if a % factor == 0:
return True
return factor == a
def F(n):
if n == 1:
return 1
if is_not_square_free(n):
return 0
return n
_CACHE = {}
def G(a, b):
a = a % DIVISOR
b = b % DIVISOR
key = (a, b) if a > b else (b, a)
if key not in _CACHE:
_CACHE[key] = (a * b * F(fractions.gcd(a, b))) % DIVISOR
return _CACHE[key]
def S(A, B):
s = 0
for a in range(1, A+1):
for b in range(1, B+1):
s += G(a, b)
return s
for _ in range(int(raw_input())):
A, B = map(int, raw_input().split())
print(S(A, B) % DIVISOR)
def gcd(a, b):
returns greatest common divisor of a and b'''
return gcd(b % a, a) if a and b else max(a, b)
print test gcd should print 6,5, 7, and 9'''
print gcd(48,18)
print gcd(10,5)
print gcd(14,21)
print gcd (9,0)

Calculating logarithm, why is this algorithm not efficient, and how to make it more efficient?

I was wondering if I could calculate the logarithm of a number based on a number relative to a base (for example, log base 2 of 16) without actually using log(). I managed to do it, but I don't believe it is very efficient.
This is my code in Python:
def myLog(x,b):
exp=0
ans=b**exp
while x!=ans:
ans=b**exp
if ans==x:
return exp
exp=exp+1
So I could give it myLog(16,2) and it should return 4. And indeed it does, however I believe it is not the most efficient way, so how could I fix it and make my code more efficient, not just in this case, but in most of them?
Try recursion:
def func(a, b, ans=0):
if a/b == 1:
return ans + 1
else: return func(a/b, b, ans+1)
In [26]: func(16, 2)
Out[26]: 4
In [27]: func(8, 2)
Out[27]: 3
In [28]: func(16,4)
Out[28]: 2
Here's my two cents worth:
def myLog(x,b):
exp = 0
ans = 1
while ans<x:
ans *= b
exp += 1
if ans == x:
return exp
else:
raise ValueError("can't find a suitable exponent")
In [10]: myLog(16,2)
Out[10]: 4
Hope this helps
You're not taking into account if someone gives a negative value such as myLog(-1,2) or if it is 1 myLog(1,2), then you compute ans before the loop which you know it always be 0 because you put exp = 0, then in the loop you compute it again without before changing the exp.
logarithm python
Assumes:
x: a positive integer
b: a positive integer; b >= 2
returns: log_b(x), or, the logarithm of x relative to a base b.
Seems the shortest way is:
def myLog(x, b):
ans = 0
while b <= x:
ans += 1
x /= b
return ans
Or recursively:
def myLog(x, b):
if (b > x): return 0
else: return 1 + myLog(x/b, b)
Because it is an endless loop:
def myLog(x,b):
exp = 0
ans = b**exp
while x != ans:
ans = b**exp
if ans>x:
return -1
if ans == x:
return exp
exp = exp+1
See also:
What algorithm is used by computers to calculate logarithms?
Taylor series
This version adds support for non-integer outputs:
def log(a, b):
b = float(b)
a = float(a)
g = a
n = 0
i = 1
while b**i != 1:
while g >= b**i:
g /= b**i
n += i
i /= b
return n
def log(a, b):
b = float(b)
a = float(a)
g = a
n = 0
i = 1
while b**i != 1:
while g >= b**i:
g /= b**i
n += i
i /= b
return n
Does not work for all numbers. log(5,10) returns 0.00000 when it should be 0.69897

Categories

Resources