Generating float numbers from integer decimal index in Python - python

Given I have any given index integer how can I generate float numbers or strings which references the decimal point as 0
Examples:
Given an increment factor digit 1:
n=-4 ~ "0.0001"
n=-10 ~ "0.0000000001"
Given an increment factor digit 2:
n=1 ~ "2.0"
n=5 ~ "20000.0"
n=-5 ~ "0.00002"

Just use scientific notation:
n = 1e-4 # 0.0001
n = 1e-10 # 0.0000000001
n = 2e1 # 2.0
n = 2e5 # 20000.0
n = 2e-5 # 0.00005
This is built into python. Doing something like
x = 5.3e6
is equivalent to doing
x = 5.3 * (10 ** 6)
It is worth noting that while the number before e may be a float itself, the number after e (the power of 10) must be an integer. Also note that this returns floating point numbers always so if you wanted it as a string for some reason you would have to call str() on the result.

Seems like you just need a power of ten in there. So take the digit, d, and multiply it by 10^n. When doing this however you should take note that the positive numbers are one factor of 10 off since it starts at 0, not 1. To fix that just subtract one from n if it's positive. This lambda does the trick: lambda n: n-1 if (n>0) else n
# When the factor (d) is 1
n=2 f = d*10^n "100.0"
n=-1 f = d*10^n "0.1"
# When the factor (d) is 2
n = 4 f = d*10^n "20000.0"
n = -5 f = d*10^n "0.00002"

Related

Lowest base system that has all 1s in its digits

I need to determine the lowest number base system in which the input n (base 10), expressed in this number base system, is all 1s in its digits.
Examples:
7 in base 2 is 111 - fits! answer is 2
21 in base 2 is 10101 - contains 0, does not fit
21 in base 3 is 210 - contains 0 and 2, does not fit
21 in base 4 is 111 - contains only 1 it fits! answer is 4
n is always less than Number.MAX_SAFE_INTEGER or equivalent.
I have the following code, which works well with a certain range of numbers, but for huge numbers the algorithm is still time consuming:
def check_digits(number, base):
res = 1
while res == 1 and number:
res *= number % base
number //= base
return res
def get_min_base(number):
for i in range(2, int(number ** 0.5) + 2):
if check_digits(number, i) == 1:
return i
return number - 1
How can I optimize the current code to make it run faster?
The number represented by a string of x 1s in base b is b^(x-1) + b^(x-2) + ... + b^2 + b + 1.
Note that for x >= 3, this number is greater than b^(x-1) (trivially) and less than (b+1)^(x-1) (apply the binomial theorem). Thus, if a number n is represented by x 1s in base b, we have b^(x-1) < n < (b+1)^(x-1). Applying x-1'th roots, we have b < n^(1/(x-1)) < b+1. Thus, for b to exist, b must be floor(n^(1/(x-1)).
I've written things with ^ notation instead of Python-style ** syntax so far because those equations and inequalities only hold for exact real number arithmetic, not for floating point. If you try to compute b with floating point math, rounding error may throw off your calculations, especially for extremely large inputs where the ULP is greater than 1. (I think floating point is fine for the input range you're working with, but I'm not sure.)
Still, regardless of whether floating point is good enough or if you need something fancier, the idea of an algorithm is there: you can directly check if a value of x is viable by directly computing what the corresponding b would have to be, and checking if x 1s in base b really represent n.
Just some small twist, slightly faster but don't improve the time complexity.
def check_digits2(number, base):
while number % base == 1:
if number == 1:
return True
number //= base
return False
def get_min_base2(number):
for i in range(2, int(number**0.5) + 2):
if check_digits2(number, i):
return i
return number - 1
def test():
number = 100000010000001
start = time.time()
print(get_min_base(number)) # 10000000
print(f"{time.time() - start:.3f}s\n") # 3.292s
start = time.time()
print(get_min_base2(number)) # 10000000
print(f"{time.time() - start:.3f}s\n") # 1.731s
Also try to approach with some math trick, but I actually make it worse lol
def calculate_n(number, base):
return math.log(number * (base - 1) + 1, base).is_integer()
def get_min_base3(number):
for i in range(2, int(number**0.5) + 2):
if calculate_n(number, i):
return i
return number - 1
def test():
number = 100000010000001
start = time.time()
print(get_min_base3(number)) # 10000000
print(f"{time.time() - start:.3f}s\n") # 4.597s

Code for factoring doesn't work with large numbers?

I have a large 512 bit number n and I need to rewrite n-1 as m*2k
Here is the code I wrote:
# write (n-1) = m*2^k (where m is odd)
k = 0 # number of times we were able to divide by 2
total = (n-1)
while total % 2 == 0:
total /= 2
k += 1
m = int(total)
assert (n-1) == (2**k) * m # this does not hold true for large values of n for some reason
The problem is that it doesn't work for large (515 bit) values of n such as:
8711599454063889217821738854601954834373650047096243407624954758041578156381215983765719390767527065267731131102484447503200895621045535585981917487924709
For the above value of n, my code found k = 460 and m =2926172291557515
When I evaluate 2926172291557515 * 2**460 in python I get:
8711599454063889889401923055669626316647070894345982715097720460936366477064539266279767451213791729696559357170292404522606916263895951485640687369584640
Which does not equal n-1. Does anyone know why this could be happening? I assume it's related to having such large numbers (this code works fine for lower numbers that I test it with.
The problem arises because you are using /= which is float division. Replace it with //=, or integer division, and your code will work.
#Primusa is correct. In Python3.x / (or /=) returns a float value, so loses a lot of precision.
>>> n = 8711599454063889217821738854601954834373650047096243407624954758041578156381215983765719390767527065267731131102484447503200895621045535585981917487924709
>>> total = (n-1)
>>> total / 2
4.355799727031945e+153
>>> total // 2
4355799727031944608910869427300977417186825023548121703812477379020789078190607991882859695383763532633865565551242223751600447810522767792990958743962354

Finding max of ANDing between two numbers in Python

I am a beginner to Python coding. I have two numbers A and B from user.
My problem is to find the max(P AND Q) where A <= P < Q <= B
I have two solutions right now for this.
Solution 1 : # ANDing with all combinations, This solution works if combinations are less. For higher values, it throws memory exceeding error.
given = raw_input()
n= list(map(int,given.split()))
A = n[0]
B = n[1]
newlist = range(B+1)
# print newlist
# Finding all combinations
comb = list(itertools.combinations(newlist,2))
# print comb
# ANDing
l = []
for i in com:
x = i[0] & i[1]
l.append(x)
# print l
print max(l)
Solution 2: After observing many input-outputs, when B == Odd, max(value) = B-1 and for B == Even, max(value) = B-2.
given = raw_input()
n= list(map(int,given.split()))
A = n[0]
B = n[1]
if B % 2 == 0:
print (B - 2)
else:
print (B -1)
According to the problem statement I am not using any ANDing for Solution 2. Still I am getting correct output.
But I am looking for much easier and Pythonic logic. Is there any other way/logic to solve this?
Your second solution is the optimal solution. But why? First, consider that a logical AND is performed on the binary representation of a number, and it is only possible to produce a number less than or equal to the smallest operand of the AND operator. For instance, 9 is represented as 1001, and there is no number that 9 can be anded with that produces a number higher than 9. Indeed, the only possible outputs for anding another number with 9 would be 9, 8, 1 and 0. Or alternatively, the biggest result from anding 9 with a number smaller than 9, is 9 less its least significant bit (so 8). If you're not sure of the binary representation of a number you can always use the bin function. eg. bin(9) => '0b1001'.
Let's start with odd numbers (as they're the easiest). Odd numbers are easy because they always have a bit in the unit position. So the maximum possible number that we can get is B less that bit in the unit position (so B - 1 is the maximum). For instance, 9 is represented as 1001. Get rid of the unit bit and we have 1000 or 8. 9 and 8 == 8, so the maximum result is 8.
Now let's try something similar with evens. For instance, 14 is represented as 1110. The maximum number we can get from anding 14 with another number would be 1100 (or 12). Like with odds, we must always lose one bit, and the smallest possible bit that can be lost is the bit in 2s position. Here, we're fortunate as 14 already as a bit in the 2s position. But what about numbers that don't? Let's try 12 (represented as 1100). If we lost the smallest bit from 12, we would have 1000 or 8. However, this is not the maximum possible. And we can easily prove this, because the maximum for 11 is 10 (since we have shown the maximum for an odd number is the odd number less 1).
We have already shown that the biggest number that can be produced from anding two different numbers is the bigger number less its least significant bit. So if that bit has a value of 2 (in the case of 14), when we can just lose that bit. If that bit has a value higher than 2 (in the case of 12), then we know the maximum is the maximum of the biggest odd number less than B (which is 1 less than the odd number and 2 less than B).
So there we have it. The maximum for an odd number is the number less 1. And the maximum for an even number is the number less 2.
def and_max(A, B): # note that A is unused
if B & 1: # has a bit in the 1 position (odd)
P, Q = B - 1, B
else:
P, Q = B - 2, B - 1
# print("P = ", P, "Q = ", Q)
return P & Q # essentially, return P
Note that none of this covers negative numbers. This is because most representations of negative numbers are in two's complement. What this means is that all negative numbers are represented as constant negative number plus a positive number. For instance, using an 4-bit representation of integers the maximum possible number would be 0111 (or 7, 4 + 2 + 1). Negative numbers would be represented as -8 plus some positive number. This negative part is indicated by a leading bit. Thus -8 is 1000 (-8 + 0) and -1 is 1111 (-8 + 7). And that's the important part. As soon as you have -1, you have an all 1s bitmask which is guaranteed to lose the negative part when anded with a positive number. So the maximum for max(P and Q) where A <= P < Q <= B and A < 0 is always B. Where B < 0, we can no longer lose the negative bit and so must maximise the positive bits again.
I think this should work:
given = raw_input()
a, b = tuple(map(int,given.split()))
print(max([p & q for q in range(a,b+1) for p in range(a,q)]))
long a,b,c,ans;
for(int i=0;i<n;i++){
a=s.nextLong();
b=s.nextLong();
if(b%2==0)
ans=b-2;
else
ans=b-1;
if(ans>=a)
System.out.println(ans);
else
System.out.println(a&b);
}

Python 3 - float(X) * i = int(Z)

I have a very large number, both before and after the decimal, but for this I'll just call it 4.58.
I want to know the number, Y, that will yield me an integer if multiplied by X and not any sort of float number.
Here is my code:
from decimal import *
setcontext(ExtendedContext)
getcontext().prec = 300
x=Decimal('4.58')
while True:
i=1
a=Decimal(i*x)
if float(a).is_integer():
print(i*x)
break
else:
i=+1
However, this method is incredibly slow and inefficient. I was wondering how could I implement continued fractions or some other method to make it predict the value of Y?
Edit
The decimal module stores float numbers more accurately (As strings), so 0.5 won't become 0.499999999.
Edit 2
I've got X (4.58).
I want to know what number will multiply by X to make an integer; as efficiently as possible.
Edit 3
Okay, maybe not my best question yet.
Here's my dilemma.
I've got a number spat out from a trivial programme I made. That number is a decimal number, 1.5.
All I want to do is find what integer will multiply by my decimal to yield another integer.
For 1.5, the best answer will be 2. (1.5*2=3) (float*int=int)
My while-loop above will do that, eventually, but I just wanted to know whether there was a better way to do this, such as continued fractions; and if there was, how could I implement it.
Edit 4
Here's my code thanks to user6794072. It's lengthy but functional.
from gmpy2 import mpz, isqrt
from fractions import Fraction
import operator
import functools
from decimal import *
setcontext(ExtendedContext)
getcontext().prec = 300
def factors(n):
n = mpz(n)
result = set()
result |= {mpz(1), n}
def all_multiples(result, n, factor):
z = n
f = mpz(factor)
while z % f == 0:
result |= {f, z // f}
f += factor
return result
result = all_multiples(result, n, 2)
result = all_multiples(result, n, 3)
for i in range(1, isqrt(n) + 1, 6):
i1 = i + 1
i2 = i + 5
if not n % i1:
result |= {mpz(i1), n // i1}
if not n % i2:
result |= {mpz(i2), n // i2}
return result
j=Decimal('4.58')
a=(Fraction(j).numerator)
b=(Fraction(j).denominator)
y=(factors(a))
x=(factors(b))
q=([item for item in x if item not in y])
w=([item for item in y if item not in x]) q.extend(w)
p=(functools.reduce(operator.mul, q, 1)) ans=(p*j)
print(ans)
If I understand your question correctly, you want to find the smallest integer (i) that can be multiplied to a non-integer number (n) so that:
i*n is an integer
I would do this by finding the factors of the numerator and denominator for n. In your example, if n = 4.58, then you can extract 458 for the numerator and 100 for the denominator.
The multiples of 458 are 2 and 229
The multiples of 100 are 2, 2, 5, 5
You can cross off one instance of 2 for the numerator and denominator. Then your solution is just multiplying the remaining factors in the denominator: in this case, 2*5*5 or 50.
Well think of what if you wanted to reach z = 1 and then use the fact that z == z * 1 to scale the answer. For any float x != 0.0, y = 1/x will yield z = 1, so for arbitrary integer z, just use y = z/x.
I'm not a Python programmer, but what about round function?

Python Partial Harmonics

Could someone help check why the result is always one and let me know what I did wrong? Thanks
Correct result should be: 1/1 + 1/2 + 1/3 == 1.83333333333.
x = int(input("Enter n: "))
assert x > 0, "n must be greater than zero!"
def one_over_n(x):
result = 0
for n in range(x):
n += 1
result += 1 / n
return result
r = one_over_n(x)
print("one_over_n( {0:d} ): {1:f}" .format(x, r))
It will work correctly on python 3, but not in python 2
>>> 1/2
0
That means you are just adding zeroes, to one. You will need to change either numerator or denominator to a float number e.g. 1/2.0, so change your code to
result += 1.0 / n
See Pep 238 to see why it was changed in python 3.
btw floating point numbers can't represent all fractions, so if you are just adding fractions, you can use Fraction class e.g.
>>> from fractions import Fraction as F
>>> F(1,1) + F(1,2) + F(1,3)
Fraction(11, 6)
As an alternative, to force Python 2 perform division as you expect (rather than integer division), add:
from __future__ import division

Categories

Resources