Project Euler Problem 26:
A unit fraction contains 1 in the numerator. The decimal representation of the unit fractions with denominators 2 to 10 are given:
1/2 = 0.5
1/3 = 0.(3)
1/4 = 0.25
1/5 = 0.2
1/6 = 0.1(6)
1/7 = 0.(142857)
1/8 = 0.125
1/9 = 0.(1)
1/10 = 0.1
Where 0.1(6) means 0.166666..., and has a 1-digit recurring cycle. It can be seen that 1/7 has a 6-digit recurring cycle.
Find the value of d < 1000 for which 1/d contains the longest recurring cycle in its decimal fraction part.
Although I have already provided the correct answer to the problem (983), I still think that the code could have developed even further as I think the code I wrote could be wrong if the value of d can go over 1000.
I think the code might be wrong because the string limit of the fraction is 20 and what if there is a fraction that has over 20 recurring cycle?
I have tried using format() to increasing the string limit of the fraction, but I realise that the digits after the 20th string are not any of the repeating recurring numbers.
import time
import math
timeStart = time.time()
prime_numbers = []
def is_prime(n):
for i in range(2, int(math.sqrt(n)+1)):
if n % i == 0:
return False
return True
def numbers(n):
for number in range(2, n):
if is_prime(number):
prime_numbers.append(number)
def main():
limit = 1000
longest_recurring_cycle = 0
longest_value = 0
numbers(limit)
for d in prime_numbers:
fraction = str(1/d)
count = 1
if len(fraction) > 15:
for index, recurring_cycle in enumerate(fraction[3:10]):
if recurring_cycle == fraction[2] and recurring_cycle ==
fraction[index + 3 + count]:
break
elif count >= longest_recurring_cycle:
longest_recurring_cycle = count
longest_value = d
count += 1
print(longest_value)
print(time.time() - timeStart, "seconds")
main()
tltr I want to find a way to increase the string limit of the fraction that produces the right number.
I would recommend simulating long division. That is, the digits of 1/7 are 10//7=1, remainder is 10 - 1*7 = 3. Next decimal is 30//7 = 4. Remainder is 2. And so on, until the remainder is equal to 1 again. Then count the length of the cycle.
def cycle(denom,num=1):
digit = None
decimals=[]
while digit not in decimals:
decimals += [digit]
digit = num * 10 // denom
remainder = num * 10 - digit * denom
num = remainder
print(digit)
return len(decimals) - decimals.index(digit)
cycle(3)
Here is my code and i got the answer with in a second.I used the simple long division method and considered only remainders.Note that this code doesn't valid when the numerator isn't equal to one.When it is,the function should be develop.
def count_repeat(number):
_list = [10]
while ((_list[-1]) % number)*10 not in _list:
_list.append((_list[-1] % number)*10)
return len(_list)-_list.index((_list[-1] % number)*10)
repeat_lenth = 0
relevent_i = 2
for i in range(2, 1000):
if count_repeat(i) >= repeat_lenth:
repeat_lenth = count_repeat(i)
relevent_i = i
print(f"{i}-{repeat_lenth}")
print(relevent_i)
def repeating_cycle(denom :int, num :int=1)->int:
'''We will do long division method but we will be tracking the reminder throught the division
The reason for doing it is sometime the the number in quotient might repeat even though it is part of
full cycle. e.g. 1/17 = 0.(0588235294117647) if we were to only look at quotient then 8 is repeted just at the 4th place but our
actual cycle is of 16 digits.And this is very well known in maths'''
reminders = []
rems = None
while rems not in reminders:
reminders.append(rems)
num *= 10
rems = num % denom
# reminders.append(rems)
reminders.pop(0)
return len(reminders)
Well I show someone's answer and that person was keeping track of digits in quotient which might not always get the answer e.g. 1/17 = 0.(058823...) and we see the third 8 is directly repeated but the cycle does not repeat there, infact it repeats after 16 digits, and I that is why it is better to keep track of reminders instead of digits in quotient.
Related
So i ask the user for some numerical inputs with a loop.
After that the inputs are being processed the mathematical result is slightly different than the actual math done with a calculator.
Does it take the 0 break value as input and somehow messes up my average ?
values = []
while True:
m = float(input("Number of shares?, 0 for Exit: "))
n = float(input("Total price of purchase?, 0 for Exit:"))
if m == 0:
break
if n == 0:
break
values.append(m)
sum = n/m
print(sum)
First things first:
I assume, you want to save the prize of a transaction (shares * price), put this number in the array values and then you want to calculate the average number from your array values. Your code doesn't do that.
sum = n/m # calculates **only** n / m and saves it **only** in the variable sum.
# You overwrite sum every loop.
Try this:
values = []
while True:
m = float(input("Number of shares?, 0 for Exit: ")) # Caution! It's not a good idea to use a float here!
n = float(input("Total price of purchase?, 0 for Exit:")) # Caution! It's not a good idea to use a float here!
if m == 0:
break
if n == 0:
break
values.append(n * m) # append the price of the transaction into values
print( sum(values) / len(values) ) # gives you the average prize per transaction
Caution! Exmample: Give m = 1.1 and n = 1.1 and only one transaction. Output is 1.2100000000000002!
Why?
Short Answer:
Avoid using floats. Instead use doubles. And if you are handling currencies never ever use floats/doubles. In python you could use decimal, if you need more precision.
Long Answer:
You are trying to calculate with floats.
Most modern programming language use the standard IEEE_754-1985 to store floats. In IEEE-754, some numbers couldn't be exact represented as an float. Because of it's binary Structure. As an example the number 0.1.
1.0 as a float is:
0 01111111 00000000000000000000000
The first bit stands for the sign. If it is zero the number is a positiv number. If it is one, it is negative.
-1.0:
1 01111111 00000000000000000000000
The 8 bits after the sign-bit is the exponent.
The 23 bits after the exponent bits are the mantissa.
What happens if we have a one in the most significant bit in the mantissa?
0 01111111 10000000000000000000000
We have now a 1.0 + 2^-1. That is 1.5.
And what is:
0 01111111 01000000000000000000000
We have now a 1.0 + 2^-2. That is 1.25.
1.1 is:
0 01111111 00011001100110011001101
1.0 + 2^-4 + 2^-5 + 2^-8 + 2^-9 + 2^-12 + 2^-13 + 2^-16 + 2^-17 +2^-20 + 2^-21 + 2^-23
That's: 1.10000002384185791015625
The Single precision gives you approximately 1.10000000.
You could use Double precision. A double contains 64 bits. 1 for the sign, 11 for the exponent and 52 bit for the mantissa. But 0.1 is still only an approximately number and not exact 0.1.
Solution
from decimal import Decimal
values = []
while True:
m = Decimal(input("Number of shares?, 0 for Exit: "))
n = Decimal(input("Total price of purchase?, 0 for Exit:"))
if m == 0:
break
if n == 0:
break
values.append(n * m)
average = sum(values) / len(values)
print(average)
Im stuck on a problem where I have to write a function that converts a denary number into a binary number using the repeated division by two algorithm. Steps Include:
The number to be converted is divided by two.
The remainder from the division is the next binary digit. Digits are added to the front of the sequence.
The result is truncated so that the input to the next division by two is always an integer.
The algorithm continues until the result is 0.
Please click the link below to see what the output should be like:
https://i.stack.imgur.com/pifUO.png
def dentobi(user):
denary = user
divide = user / 2
remainder = user % 2
binary = remainder
if user != 0:
print("Denary:", denary)
print("Divide by 2:", divide)
print("Remainder:", remainder)
print("Binary:", binary)
user = int(input("Please enter a number: "))
dentobi(user)
This is what I have done so far but Im not getting anywhere.
Can someone explain how I would do this?
The Answer provided by #user2390182 is functionally correct except that it returns an empty string when num is zero. However, I have noted on several occasions that divmod() is rather slow. Here are three slightly different techniques and their performance statistics.
import time
# This is the OP's original code edited to allow for num == 0
def binaryx(num):
b = ""
while num:
num, digit = divmod(num, 2)
b = f"{digit}{b}"
return b or '0'
# This is my preferred solution
def binaryo(n):
r = []
while n > 0:
r.append('1' if n & 1 else '0')
n >>= 1
return ''.join(reversed(r)) or '0'
# This uses techniques suggested by my namesake
def binaryy(n):
r = ''
while n > 0:
r = str(n & 1) + r
n >>= 1
return r or '0'
M = 250_000
for func in [binaryx, binaryo, binaryy]:
s = time.perf_counter()
for _ in range(M):
func(987654321)
e = time.perf_counter()
print(f'{func.__name__} -> {e-s:.4f}s')
Output:
binaryx -> 1.3817s
binaryo -> 0.9861s
binaryy -> 1.6052s
One way, using divmod to divide by 2 and get the remainder in one step:
def binary(num):
b = ""
while num:
num, digit = divmod(num, 2)
b = f"{digit}{b}"
return b
binary(26)
'11010'
This assumes a positive number but can easily be extended to work for 0 and negatives.
Need help converting binary to decimal, using recursion.
So far I have :
(2* int(s[0])) + int(s[1])
with base cases for when s==0 and s==1.
I'm not sure how to pass this recursively so that the function will pass through all 1's and 0's in input,s.
The basic idea is to pick off the last character of the string and convert that to a number, then multiply it by the appropriate power of 2. I've commented the code for you.
# we need to keep track of the current string,
# the power of two, and the total (decimal)
def placeToInt (str, pow, total):
# if the length of the string is one,
# we won't call the function anymore
if (len(str) == 1):
# return the number, 0 or 1, in the string
# times 2 raised to the current power,
# plus the already accumulated total
return int(str) * (2 ** pow) + total
else:
# grab the last digit, a 0 or 1
num = int(str[-1:])
# the representation in binary is 2 raised to the given power,
# times the number (0 or 1)
# add this to the total
total += (num * (2 ** pow))
# return, since the string has more digits
return placeToInt(str[:-1], pow + 1, total)
# test case
# appropriately returns 21
print(placeToInt("10101", 0, 0))
Now, let's go through it manually, so you understand why this works.
# n = 101 (in binary
# this can also be represented as 1*(2^2) + 0*(2^1) + 1*(2^0)
# alternatively, since there are three digits in this binary number
# 1*(2^(n-1)) + 0*(2^(n-2)) + 1*(2^(n-3))
So what does this mean? Well, the rightmost digit is 1 or 0 times 2 raised to the power of zero. In other words, it either adds 1 or 0 to the total. What about the second rightmost digit? It either adds 0 or 2 to the total. The next one? 0 or 4. See the pattern?
Let's write the pseudocode:
let n = input, in binary
total = 0
power of 2 = 0
while n has a length:
lastDigit = last digit of n
add (2^pow)*lastDigit to the current total
Since we start with a power and a total of 0, you can see why this works.
def IntegerConvert(num, base):
if num == 0:
return 0
else:
IntegerConvert.sum += pow(10, IntegerConvert.counter)*(num % base)
IntegerConvert.counter += 1
IntegerConvert(num/base, base)
return IntegerConvert.sum
IntegerConvert.counter = 0
IntegerConvert.sum = 0
print IntegerConvert(10, 2)
I want to generate the digits of the square root of two to 3 million digits.
I am aware of Newton-Raphson but I don't have much clue how to implement it in C or C++ due to lack of biginteger support. Can somebody point me in the right direction?
Also, if anybody knows how to do it in python (I'm a beginner), I would also appreciate it.
You could try using the mapping:
a/b -> (a+2b)/(a+b) starting with a= 1, b= 1. This converges to sqrt(2) (in fact gives the continued fraction representations of it).
Now the key point: This can be represented as a matrix multiplication (similar to fibonacci)
If a_n and b_n are the nth numbers in the steps then
[1 2] [a_n b_n]T = [a_(n+1) b_(n+1)]T
[1 1]
which now gives us
[1 2]n [a_1 b_1]T = [a_(n+1) b_(n+1)]T
[1 1]
Thus if the 2x2 matrix is A, we need to compute An which can be done by repeated squaring and only uses integer arithmetic (so you don't have to worry about precision issues).
Also note that the a/b you get will always be in reduced form (as gcd(a,b) = gcd(a+2b, a+b)), so if you are thinking of using a fraction class to represent the intermediate results, don't!
Since the nth denominators is like (1+sqrt(2))^n, to get 3 million digits you would likely need to compute till the 3671656th term.
Note, even though you are looking for the ~3.6 millionth term, repeated squaring will allow you to compute the nth term in O(Log n) multiplications and additions.
Also, this can easily be made parallel, unlike the iterative ones like Newton-Raphson etc.
EDIT: I like this version better than the previous. It's a general solution that accepts both integers and decimal fractions; with n = 2 and precision = 100000, it takes about two minutes. Thanks to Paul McGuire for his suggestions & other suggestions welcome!
def sqrt_list(n, precision):
ndigits = [] # break n into list of digits
n_int = int(n)
n_fraction = n - n_int
while n_int: # generate list of digits of integral part
ndigits.append(n_int % 10)
n_int /= 10
if len(ndigits) % 2: ndigits.append(0) # ndigits will be processed in groups of 2
decimal_point_index = len(ndigits) / 2 # remember decimal point position
while n_fraction: # insert digits from fractional part
n_fraction *= 10
ndigits.insert(0, int(n_fraction))
n_fraction -= int(n_fraction)
if len(ndigits) % 2: ndigits.insert(0, 0) # ndigits will be processed in groups of 2
rootlist = []
root = carry = 0 # the algorithm
while root == 0 or (len(rootlist) < precision and (ndigits or carry != 0)):
carry = carry * 100
if ndigits: carry += ndigits.pop() * 10 + ndigits.pop()
x = 9
while (20 * root + x) * x > carry:
x -= 1
carry -= (20 * root + x) * x
root = root * 10 + x
rootlist.append(x)
return rootlist, decimal_point_index
As for arbitrary big numbers you could have a look at The GNU Multiple Precision Arithmetic Library (for C/C++).
For work? Use a library!
For fun? Good for you :)
Write a program to imitate what you would do with pencil and paper. Start with 1 digit, then 2 digits, then 3, ..., ...
Don't worry about Newton or anybody else. Just do it your way.
Here is a short version for calculating the square root of an integer a to digits of precision. It works by finding the integer square root of a after multiplying by 10 raised to the 2 x digits.
def sqroot(a, digits):
a = a * (10**(2*digits))
x_prev = 0
x_next = 1 * (10**digits)
while x_prev != x_next:
x_prev = x_next
x_next = (x_prev + (a // x_prev)) >> 1
return x_next
Just a few caveats.
You'll need to convert the result to a string and add the decimal point at the correct location (if you want the decimal point printed).
Converting a very large integer to a string isn't very fast.
Dividing very large integers isn't very fast (in Python) either.
Depending on the performance of your system, it may take an hour or longer to calculate the square root of 2 to 3 million decimal places.
I haven't proven the loop will always terminate. It may oscillate between two values differing in the last digit. Or it may not.
The nicest way is probably using the continued fraction expansion [1; 2, 2, ...] the square root of two.
def root_two_cf_expansion():
yield 1
while True:
yield 2
def z(a,b,c,d, contfrac):
for x in contfrac:
while a > 0 and b > 0 and c > 0 and d > 0:
t = a // c
t2 = b // d
if not t == t2:
break
yield t
a = (10 * (a - c*t))
b = (10 * (b - d*t))
# continue with same fraction, don't pull new x
a, b = x*a+b, a
c, d = x*c+d, c
for digit in rdigits(a, c):
yield digit
def rdigits(p, q):
while p > 0:
if p > q:
d = p // q
p = p - q * d
else:
d = (10 * p) // q
p = 10 * p - q * d
yield d
def decimal(contfrac):
return z(1,0,0,1,contfrac)
decimal((root_two_cf_expansion()) returns an iterator of all the decimal digits. t1 and t2 in the algorithm are minimum and maximum values of the next digit. When they are equal, we output that digit.
Note that this does not handle certain exceptional cases such as negative numbers in the continued fraction.
(This code is an adaptation of Haskell code for handling continued fractions that has been floating around.)
Well, the following is the code that I wrote. It generated a million digits after the decimal for the square root of 2 in about 60800 seconds for me, but my laptop was sleeping when it was running the program, it should be faster that. You can try to generate 3 million digits, but it might take a couple days to get it.
def sqrt(number,digits_after_decimal=20):
import time
start=time.time()
original_number=number
number=str(number)
list=[]
for a in range(len(number)):
if number[a]=='.':
decimal_point_locaiton=a
break
if a==len(number)-1:
number+='.'
decimal_point_locaiton=a+1
if decimal_point_locaiton/2!=round(decimal_point_locaiton/2):
number='0'+number
decimal_point_locaiton+=1
if len(number)/2!=round(len(number)/2):
number+='0'
number=number[:decimal_point_locaiton]+number[decimal_point_locaiton+1:]
decimal_point_ans=int((decimal_point_locaiton-2)/2)+1
for a in range(0,len(number),2):
if number[a]!='0':
list.append(eval(number[a:a+2]))
else:
try:
list.append(eval(number[a+1]))
except IndexError:
pass
p=0
c=list[0]
x=0
ans=''
for a in range(len(list)):
while c>=(20*p+x)*(x):
x+=1
y=(20*p+x-1)*(x-1)
p=p*10+x-1
ans+=str(x-1)
c-=y
try:
c=c*100+list[a+1]
except IndexError:
c=c*100
while c!=0:
x=0
while c>=(20*p+x)*(x):
x+=1
y=(20*p+x-1)*(x-1)
p=p*10+x-1
ans+=str(x-1)
c-=y
c=c*100
if len(ans)-decimal_point_ans>=digits_after_decimal:
break
ans=ans[:decimal_point_ans]+'.'+ans[decimal_point_ans:]
total=time.time()-start
return ans,total
Python already supports big integers out of the box, and if that's the only thing holding you back in C/C++ you can always write a quick container class yourself.
The only problem you've mentioned is a lack of big integers. If you don't want to use a library for that, then are you looking for help writing such a class?
Here's a more efficient integer square root function (in Python 3.x) that should terminate in all cases. It starts with a number much closer to the square root, so it takes fewer steps. Note that int.bit_length requires Python 3.1+. Error checking left out for brevity.
def isqrt(n):
x = (n >> n.bit_length() // 2) + 1
result = (x + n // x) // 2
while abs(result - x) > 1:
x = result
result = (x + n // x) // 2
while result * result > n:
result -= 1
return result
I'm trying to convert a floating point number to binary representation; how can I achieve this?
My goal is, however, not to be limited by 2m so I'm hoping for something that could be easily extended to any base (3, 4, 8) ecc.
I've got a straightforward implementation so far for integers:
import string
LETTER = '0123456789' + string.ascii_lowercase
def convert_int(num, base):
if base == 1:
print "WARNING! ASKING FOR BASE = 1"
return '1' * num if num != 0 else '0'
if base > 36: raise ValueError('base must be >= 1 and <= 36')
num, rest = divmod(num, base)
rest = [LETTER[rest]]
while num >= base:
num, r = divmod(num, base)
rest.append(LETTER[r])
rest.reverse()
return (LETTER[num] if num else '') + ''.join(str(x) for x in rest)
any help appreciated :)
edit:
def convert_float(num, base, digits=None):
num = float(num)
if digits is None: digits = 6
num = int(round(num * pow(base, digits)))
num = convert_int(num, base)
num = num[:-digits] + '.' + num[:digits]
if num.startswith('.'): num = '0' + num
return num
is that right? why do i get this behaviour?
>>> convert_float(1289.2893, 16)
'509.5094a0'
>>> float.hex(1289.2983)
'0x1.42531758e2196p+10'
p.s.
How to convert float number to Binary?
I've read that discussion, but I don't get the answer.. I mean, does it work only for 0.25, 0.125? and I dont understand the phrase 'must be in reverse order'...
For floats there is built-in method hex().
http://docs.python.org/library/stdtypes.html#float.hex
It gives you the hexadecimal representation of a given number. And translation form hex to binary is trivial.
For example:
In [15]: float.hex(1.25)
Out[15]: '0x1.4000000000000p+0'
In [16]: float.hex(8.25)
Out[16]: '0x1.0800000000000p+3'
Next answer with a bit of theory.
Explanation below does not explain IEEE Floating Point standard only general ideas concerning representation of floating point numbers
Every float number is represented as a fractional part multiplied by an exponent multiplied by a sign. Additionally there is so called bias for exponent, which will be explained bellow.
So we have
Sign bit
Fractional part digits
Exponent part digits
Example for base 2 with 8 bit fraction and 8 bit exponent
Bits in fraction part tell us which summands (numbers to be added) from sequence below are to be included in represented number value
2^-1 + 2^-2 + 2^-3 + 2^-4 + 2^-5 + 2^-6 + 2^-7 + 2^-8
So if you have say 01101101 in fractional part it gives
0*2^-1 + 1*2^-2 + 1*2^-3 + 0*2^-4 + 1*2^-5 + 1*2^-6 + 0*2^-7 + 1*2^-8 = 0.42578125
Now non-zero numbers that are representable that way fall between
2 ** -8 = 0.00390625 and 1 - 2**-8 = 0.99609375
Here the exponent part comes in. Exponent allows us to represent very big numbers by multiplying the fraction part by exponent. So if we have an 8bit exponent we can multiply the resulting fraction by numbers between 0 and 2^255.
So going back to example above let's take exponent of 11000011 = 195.
We have fractional part of 01101101 = 0.42578125 and exponent part 11000011 = 195. It gives us the number 0.42578125 * 2^195, this is really big number.
So far we can represent non-zero numbers between 2^-8 * 2^0 and (1-2^-8) * 2^255. This allows for very big numbers but not for very small numbers. In order to be able to represent small numbers we have to include so called bias in our exponent. It is a number that will be always subtracted from exponent in order to allow for representation of small numbers.
Let's take a bias of 127. Now all exponents are subtracted 127. So numbers that can be represented are between 2^-8 * 2^(0 - 127) and (1-2^-8) * 2^(255 - 127 = 128)
Example number is now 0.42578125 * 2^(195-127 = 68) which is still pretty big.
Example ends
In order to understand this better try to experiment with different bases and sizes for fractional and exponential part. At beginning don't try with odd bases because it only complicates things necessary.
Once you grasp how this representation works you should be able to write code to obtain representation of any number in any base, fractional/exponential part combination.
If you want to convert a float to a string with d digits after the decimal radix point:
Multiply the number by base**d.
Round to the nearest integer.
Convert the integer to a string.
Insert the . character d digits before the end.
For example, to represent 0.1 in base 12 with 4 decimal dozenal places,
0.1 × 124 = 2073.6
Round to nearest integer → 2074
Convert to string → 124A
Add radix point → 0.124A
This isn't the same style of binary representation that you want, but this will convert an IEEE 754 into it's sign, mantissa and base, which can be used to create a hex representation in a fairly straightforward fashion. Note that the 'value' of the mantissa is 1+BINARY, where BINARY is the binary representation - hence the -1 in the return.
I wrote this code and am declaring it public domain.
def disect_float(f):
f = float(f); #fixes passing integers
sign = 0x00; #positive
exp = 0;
mant = 0;
if(f < 0): #make f positive, store the sign
sign = '-'; #negative
f = -f;
#get the mantissa by itself
while(f % 1 > 0): #exp is positive
f*=2
exp+=1
#while(f % 1 > 0):
tf = f/2;
while(tf % 1 <= 0): #exp is negative
exp-=1;
f=tf;
tf=f/2;
if(exp < -1024): break;
mant=int(f);
return sign, mant-1, exp;
There is one trick that i observed that we can do using simple string manipulations. I felt this method to be simpler than other methods that i came across.
s = "1101.0101"
s1, s2 = s.split(".")
s1 = int(s1, 2)
s2 = int(s2, 2)/(2**len(s2))
x = s1+s2
print(x)
Output :
13.3125
Hope it will be helpful to someone.
Answering the title directly and using float.hex, which uses 64bit IEE754, one could write this method:
def float_to_bin(x):
if x == 0:
return "0" * 64
w, sign = (float.hex(x), 0) if x > 0 else (float.hex(x)[1:], 1)
mantissa, exp = int(w[4:17], 16), int(w[18:])
return "{}{:011b}{:052b}".format(sign, exp + 1023, mantissa)
float_to_bin(-0.001) # '1011111101010000000010110011111101011000011011100110110100101010'
Note however, this does not work for NaN and Inf.