These 2 functions perform Extended Euclidean Algorithm, and then find the multiplicative inverse. The order seems right, but it's not coming back with what I'm expecting as per this tool from U of Sydney http://magma.maths.usyd.edu.au/calc/ and since this is done in the GF(2) finite field, I think I'm missing some key step that translates from base 10 into this field.
This was tested and worked on base 10, but taking in polynomials with binary coefficients might not be possible here. So my question is what parts of Python am I incorrectly applying to this algorithm, such as // floor, that may not carry from what the function was capable of in base 10 to be able to do this in GF(2).
The tool above can be tested like this:
R<x>:=PolynomialRing(GF(2));
p:=x^13+x+1; q:=x^12+x;
g,r,s:=XGCD(p,q);
g eq r*p+s*q;
g,r,s;
The functions:
def extendedEuclideanGF2(self,a,b): # extended euclidean. a,b are values 10110011... in integer form
inita,initb=a,b; x,prevx=0,1; y,prevy = 1,0
while b != 0:
q = int("{0:b}".format(a//b),2)
a,b = b,int("{0:b}".format(a%b),2);
x,prevx = (int("{0:b}".format(prevx-q*x)), int("{0:b}".format(x,2))); y,prevy=(prevy-q*y, y)
print("Euclidean %d * %d + %d * %d = %d" % (inita,prevx,initb,prevy,a))
return a,prevx,prevy # returns gcd of (a,b), and factors s and t
def modular_inverse(self,a,mod): # a,mod are integer values of 101010111... form
a,mod = prepBinary(a,mod)
bitsa = int("{0:b}".format(a),2); bitsb = int("{0:b}".format(mod),2)
#return bitsa,bitsb,type(bitsa),type(bitsb),a,mod,type(a),type(mod)
gcd,s,t = extendedEuclideanGF2(a,mod); s = int("{0:b}".format(s))
initmi = s%mod; mi = int("{0:b}".format(initmi))
print ("M Inverse %d * %d mod %d = 1"%(a,initmi,mod))
if gcd !=1: return mi,False
return mi # returns modular inverse of a,mod
I've been testing with polynomials like this but in binary form of course:
p = "x**13 + x**1 + x**0"
q = "x**12 + x**1"
The function worked when tested with base-10 because all of your conversions int("{0:b}".format(x)) have no effect on x:
37 == int("{0:b}".format(37), 2) # >>> True
Number objects in python are all base-10. Converting your numbers to binary strings, then back to integers has no effect. Here is an alternative version of your function that should work on a and b as base-10 ints and return them in binary. You can remove the bin() function to return the numbers in base-10, or use something like lambda x: int("%d".format(x)) to convert a and b from binary to decimal in the first line of the function.
def extendedEuclideanGF2(a, b): # extended euclidean. a,b are values 10110011... in integer form
inita, initb = a, b # if a and b are given as base-10 ints
x, prevx = 0, 1
y, prevy = 1, 0
while b != 0:
q = a//b
a, b = b, a%b
x, prevx = prevx - q*x, x
y, prevy = prevy - q*y, y
print("Euclidean %d * %d + %d * %d = %d" % (inita, prevx, initb, prevy, a))
i2b = lambda n: int("{0:b}".format(n)) # convert decimal number to a binary value in a decimal number
return i2b(a), i2b(prevx), i2b(prevy) # returns gcd of (a,b), and factors s and t
All that said, don't use lambdas in a function like this - I'd suggest writing your program to avoid using binary altogether, which you can do by only converting from/to binary at the interface of your program with source data.
Related
I was bored at work and was playing with some math and python coding, when I noticed the following:
Recursively (or if using a for loop) you simply add integers together to get a given Fibonacci number. However there is also a direct equation for calculating Fibonacci numbers, and for large n this equation will give answers that are, frankly, quite wrong with respect to the recursively calculated Fibonacci number.
I imagine this is due to rounding and floating point arithmetic ( sqrt(5) is irrational after all), and if so can anyone point me into a direction on how I could modify the fibo_calc_direct function to return a more accurate result?
Thanks!
def fib_calc_recur(n, ii = 0, jj = 1):
#n is the index of the nth fibonacci number, F_n, where F_0 = 0, F_1 = 1, ...
if n == 0: #use recursion
return ii
if n == 1:
return jj
else:
return(fib_calc_recur(n -1, jj, ii + jj))
def fib_calc_direct(n):
a = (1 + np.sqrt(5))/2
b = (1 - np.sqrt(5))/2
f = (1/np.sqrt(5)) * (a**n - b**n)
return(f)
You could make use of Decimal numbers, and set its precision depending on the magninute of n
Not your question, but I'd use an iterative version of the addition method. Here is a script that makes both calculations (naive addition, direct with Decimal) for values of n up to 4000:
def fib_calc_iter(n):
a, b = 0, 1
if n < 2:
return n
for _ in range(1, n):
a, b = b, a + b
return b
from decimal import Decimal, getcontext
def fib_calc_decimal(n):
getcontext().prec = n // 4 + 3 # Choose a precision good enough for this n
sqrt5 = Decimal(5).sqrt()
da = (1 + sqrt5) / 2
db = (1 - sqrt5) / 2
f = (da**n - db**n) / sqrt5
return int(f + Decimal(0.5)) # Round to nearest int
# Test it...
for n in range(1, 4000):
x = fib_calc_iter(n)
y = fib_calc_decimal(n)
if x != y:
print(f"Difference found for n={n}.\nNaive method={x}.\nDecimal method={y}")
break
else:
print("No differences found")
Today I wrote a naive function that converts a float to a string by repeatedly modding by 10 and dividing by 10.
def to_string(x):
r = ""
while x >= 1.0:
r = str(int(x%10)) + r
x /= 10.0
return r
I then tested my function against Python's built-in capability to convert a float to a string. Not too surprisingly, my function differs on large numbers.
>>> to_string(1e30)
'1000000000000000424684240284426'
>>> "%.f"%1e30
'1000000000000000019884624838656'
So, my question is: what computation do I have to do to get the digits that Python gets?
Here is a very simple solution. It is not intended to be efficient or to handle any values other than positive integers.
#!/usr/bin/python
import math
# This code represents a hexadecimal number using a list in which each item
# is a single hexadecimal digit (an integer from 0 to 15).
# Divide the base-16 digit-list in x by digit d. This uses grade-school
# division, for a single-digit divisor. It returns the quotient in a new
# digit-list and the remainder as a plain integer.
def Divide(x, d):
# If the first digit is smaller than d, start an empty quotient with
# a remainder being carried.
if x[0] < d:
q = []
r = x[0]
# Otherwise, start the quotient by dividing the first digit by d.
else:
q = [x[0] / d]
r = x[0] % d
# For the remaining digits, multiply the remainder by the base and
# add the new digit. Then divide by d, calculating a new digit of the
# quotient and a new remainder to carry.
for i in x[1:]:
r = r*16 + i
q.append(r/d)
r = r % d
return (q, r)
# Convert a positive integer floating-point value to decimal and print it.
def to_string(x):
# Convert input to base 16. This has no rounding errors since the
# floating-point format uses base two, and 16 is a power of two.
t= []
while 0 < x:
# Use remainder modulo 16 to calculate the next digit, then insert it.
t.insert(0, int(x % 16))
# Remove the digit from x.
x = math.floor(x/16)
# Start an empty output string.
output = ""
# Divide the number by 10 until it is zero (is an empty digit list).
# Each time we divide, the remainder is a new digit of the answer.
while t != []:
(t, r) = Divide(t, 10)
output = str(r) + output
print output
to_string(1e30)
To explain this, this is basically a way to shrink floating point vector data into 8-bit or 16-bit signed or unsigned integers with a single common unsigned exponent (the most common of which being bs16 for precision with a common exponent of 11).
I'm not sure what this pseudo-float method is called; all I know is to get the resulting float, you need to do this:
float_result = int_value / ( 2.0 ** exponent )
What I'd like to do is match this data by basically guessing the exponent by attempting to re-calculate it from the given floats.
(if done properly, it should be able to be re-calculated in other formats as well)
So if all I'm given is a large group of 1140 floats to work with, how can I find the common exponent and convert these floats into this shrunken bu8, bs8, bu16, or bs16 (specified) format?
EDIT: samples
>>> for value in array('h','\x28\xC0\x04\xC0\xF5\x00\x31\x60\x0D\xA0\xEB\x80'):
print( value / ( 2. ** 11 ) )
-7.98046875
-7.998046875
0.11962890625
12.0239257812
-11.9936523438
-15.8852539062
EDIT2:
I wouldn't exactly call this "compression", as all it really is, is an extracted mantissa to be re-computed via the shared exponent.
Maybe something like this:
def validExponent(x,e,a,b):
"""checks if x*2.0**e is an integer in range [a,b]"""
y = x*2.0**e
return a <= y <= b and y == int(y)
def allValid(xs,e,a,b):
return all(validExponent(x,e,a,b) for x in xs)
def firstValid(xs,a,b,maxE = 100):
for e in xrange(1+maxE):
if allValid(xs,e,a,b):
return e
return "None found"
#test:
xs = [x / ( 2. ** 11 ) for x in [-12,14,-5,16,28]]
print xs
print firstValid(xs,-2**15,2**15-1)
Output:
[-0.005859375, 0.0068359375, -0.00244140625, 0.0078125, 0.013671875]
11
You could of course write a wrapper function which will take a string argument such as 'bs16' and automatically compute the bounds a,b
On Edit:
1) If you have the exact values of the floats the above should work. It anything has introduced any round-off error you might want to replace y == int(y) by abs(y-round(y)) < 0.00001 (or something similar).
2) The first valid exponent will be the exponent you want unless all of the integers in the original integer list are even. If you have 1140 values and they are in some sense random, the chance of this happening is vanishingly small.
On Further Edit: If the floats in question are not generated by this process but you want to find an optimal exponent which allows for (lossy) compression to ints of a given size you can do something like this (not thoroughly tested):
import math
def maxExp(x,a,b):
"""returns largest nonnegative integer exponent e with
a <= x*2**e <= b, where a, b are integers with a <= 0 and b > 0
Throws an error if no such e exists"""
if x == 0.0:
e = -1
elif x < 0.0:
e = -1 if a == 0 else math.floor(math.log(a/float(x),2))
else:
e = math.floor(math.log(b/float(x),2))
if e >= 0:
return int(e)
else:
raise ValueError()
def bestExponent(floats,a,b):
m = min(floats)
M = max(floats)
e1 = maxExp(m,a,b)
e2 = maxExp(M,a,b)
MSE = []
for e in range(1+min(e1,e2)):
MSE.append(sum((x - round(x*2.0**e)/2.0**e)**2 for x in floats)/float(len(floats)))
minMSE = min(MSE)
for e,error in enumerate(MSE):
if error == minMSE:
return e
To test it:
>>> import random
>>> xs = [random.uniform(-10,10) for i in xrange(1000)]
>>> bestExponent(xs,-2**15,2**15-1)
11
It seems like the common exponent 11 is chosen for a reason.
If you've got the original values, and the corresponding result, you can use log to find the exponent. Math has a log function you can use. You'd have to log Int_value/float_result to the base 2.
EG:
import Math
x = (int_value/float_result)
math.log(x,2)
I have two numbers, p, and q. I know that I can get phi = (p-1)*(q-1) and that ed = 1 (mod phi)... but I'm not sure I get what this means.
I wrote some Python:
p = NUM
q = NUM
e = NUM
phi = (p-1)*(q-1)
d = (1 % phi)/float(e)
But I always get a decimal, and d is supposed to be an integer. what am I doing wrong?
EDIT: I may just not understand RSA. Right now, I'm looking at this page: http://www.di-mgt.com.au/rsa_alg.html
Your understanding of the math is wrong. The equation
ed ≡ 1 (mod φ)
means that, the remainder of number ed dividing φ is equal to 1, i.e. in terms of Python,
>>> (e*d) % phi
1
For instance, if φ = (7 - 1)(11 - 1) = 60, and e = 17, then if we choose d = 53, then we'll get
>>> e = 17
>>> d = 53
>>> phi = 60
>>> (e*d) % phi
1
We call d a modular multiplicative inverse of e.
To generate d from e and φ, usually extended Euclidean algorithm is used. Please read http://en.wikipedia.org/wiki/Modular_multiplicative_inverse or https://stackoverflow.com/search?q=python+%22multiplicative+inverse%22&submit=search for more info
Since the dnominator on the division is a float, Python will always promote the result of the division to a float.
If you want to explictely have the result as an integer, do not promote any of the operators to float, and use the "//" operator instead - it prevents, in a "future compatible" way, automatic conversion of the division result to a float.
d = (1 % phi)// e
It's returning a decimal because you're dividing by a floating point number
float(e)
You can get the final number to be converted into an integer by wrapping the whole computation in an int() function like this :
d = int( (1 mod phi)/float(e) )
How does one convert a base-10 floating point number in Python to a base-N floating point number?
Specifically in my case, I would like to convert numbers to base 3 (obtain the representation of floating point numbers in base 3), for calculations with the Cantor set.
After a bit of fiddling, here's what I came up with. I present it to you humbly, keeping in mind Ignacio's warning. Please let me know if you find any flaws. Among other things, I have no reason to believe that the precision argument provides anything more than a vague assurance that the first precision digits are pretty close to correct.
def base3int(x):
x = int(x)
exponents = range(int(math.log(x, 3)), -1, -1)
for e in exponents:
d = int(x // (3 ** e))
x -= d * (3 ** e)
yield d
def base3fraction(x, precision=1000):
x = x - int(x)
exponents = range(-1, (-precision - 1) * 2, -1)
for e in exponents:
d = int(x // (3 ** e))
x -= d * (3 ** e)
yield d
if x == 0: break
These are iterators returning ints. Let me know if you need string conversion; but I imagine you can handle that.
EDIT: Actually looking at this some more, it seems like a if x == 0: break line after the yield in base3fraction gives you pretty much arbitrary precision. I went ahead and added that. Still, I'm leaving in the precision argument; it makes sense to be able to limit that quantity.
Also, if you want to convert back to decimal fractions, this is what I used to test the above.
sum(d * (3 ** (-i - 1)) for i, d in enumerate(base3fraction(x)))
Update
For some reason I've felt inspired by this problem. Here's a much more generalized solution. This returns two generators that generate sequences of integers representing the integral and fractional part of a given number in an arbitrary base. Note that this only returns two generators to distinguish between the parts of the number; the algorithm for generating digits is the same in both cases.
def convert_base(x, base=3, precision=None):
length_of_int = int(math.log(x, base))
iexps = range(length_of_int, -1, -1)
if precision == None: fexps = itertools.count(-1, -1)
else: fexps = range(-1, -int(precision + 1), -1)
def cbgen(x, base, exponents):
for e in exponents:
d = int(x // (base ** e))
x -= d * (base ** e)
yield d
if x == 0 and e < 0: break
return cbgen(int(x), base, iexps), cbgen(x - int(x), base, fexps)
Although 8 years have passed, I think it is worthwhile to mention a more compact solution.
def baseConversion( x=1, base=3, decimals=2 ):
import math
n_digits = math.floor(-math.log(x, base))#-no. of digits in front of decimal point
x_newBase = 0#initialize
for i in range( n_digits, decimals+1 ):
x_newBase = x_newBase + int(x*base**i) % base * 10**(-i)
return x_newBase
For example calling the function to convert the number 5+1/9+1/27
def baseConversion( x=5+1/9+1/27, base=3, decimals=2 )
12.01
def baseConversion( x=5+1/9+1/27, base=3, decimals=3 )
12.011
You may try this solution to convert a float string to a given base.
def eval_strint(s, base=2):
assert type(s) is str
assert 2 <= base <= 36
###
### YOUR CODE HERE
###
return int(s,base)
def is_valid_strfrac(s, base=2):
return all([is_valid_strdigit(c, base) for c in s if c != '.']) \
and (len([c for c in s if c == '.']) <= 1)
def eval_strfrac(s, base=2):
assert is_valid_strfrac(s, base), "'{}' contains invalid digits for a base-{} number.".format(s, base)
stg = s.split(".")
float_point=0.0
if len(stg) > 1:
float_point = (eval_strint(stg[1],base) * (base**(-len(stg[1]))))
stg_float = eval_strint(stg[0],base) + float_point
return stg_float