Get the n-th double number from a given double in python - python

This question is similar to another question but I do not see how to extend the answer to that question in an easy way.
Here, I want to calculate the n-th double from a given double in Python.
The function takes an integer n, a double x, and outputs a double that is the n-th after x (or before, if n is negative). Is there an efficient way to do it?
Concretely, Let nth_fp_after be the function, then nth_fp_after(x,n) should equal to n times the application of nextafter (in C) to x; nth_fp_after(x,0) should be 'x', etc.

The answer of the question you pointed to is exactly the answer to your question. The answer solved the problem for for 64 bits float that are the python equivalent of C double.
Well, if you add the following
struct.unpack('!i',struct.pack('!f',x))[0]
to n and use it to call the function of the other answer, you should get it.
The full solution by modifying will look like:
import struct
def nth_fp(n, x=0.0):
if(x>=0):
m = n + struct.unpack('!Q',struct.pack('!d',x))[0]
else:
m = n - struct.unpack('!Q',struct.pack('!d',abs(x) ))[0]
if m < 0:
sign_bit = 0x8000000000000000
m = -m
else:
sign_bit = 0
if m >= 0x7ff0000000000000:
raise ValueError('out of range')
bit_pattern = struct.pack('Q', m | sign_bit)
return struct.unpack('d', bit_pattern)[0]
I added a default value to the second parameter so that you can used it in both cases, with or without offset x.

Related

Summation function for large integers

I am an amateur Python coder trying to find an efficient solution for Project Euler Digit Sum problem. My code returns the correct result but is is inefficient for large integers such as 1234567890123456789. I know that the inefficiency lies in my sigma_sum function where there is a 'for' loop.
I have tried various alternate solutions such as loading the values into an numpy array but ran out of memory with large integers with this approach. I am eager to learn more efficient solutions.
import math
def sumOfDigits(n: int) :
digitSum = 0
if n < 10: return n
else:
for i in str(n): digitSum += int(i)
return digitSum
def sigma_sum(start, end, expression):
return math.fsum(expression(i) for i in range(start, end))
def theArguement(n: int):
return n / sumOfDigits(n)
def F(N: int) -> float:
"""
>>> F(10)
19
>>> F(123)
1.187764610390e+03
>>> F(12345)
4.855801996238e+06
"""
s = sigma_sum(1, N + 1, theArguement)
if s.is_integer():
print("{:0.0f}".format(s))
else:
print("{:.12e}".format(s))
print(F(123))
if __name__ == '__main__':
import doctest
doctest.testmod()
Try solving a different problem.
Define G(n) to be a dictionary. Its keys are integers representing digit sums and its values are the sum of all positive integers < n whose digit sum is the key. So
F(n) = sum(v / k for k, v in G(n + 1).items())
[Using < instead of ≤ simplifies the calculations below]
Given the value of G(a) for any value, how would you calculate G(10 * a)?
This gives you a nice easy way to calculate G(x) for any value of x. Calculate G(x // 10) recursively, use that to calculate the value G((x // 10) * 10), and then manually add the few remaining elements in the range (x // 10) * 10 ≤ i < x.
Getting from G(a) to G(10 * a) is mildly tricky, but not overly so. If your code is correct, you can use calculating G(12346) as a test case to see if you get the right answer for F(12345).

Query regarding Bit Counting (Python)

I tried to solve this Kata problem
Write a function that takes an integer as input, and returns the number of bits that are equal to one in the binary representation of that number. You can guarantee that input is non-negative.
Example: The binary representation of 1234 is 10011010010, so the function should return 5 in this case.
But the problem is my code gives the correct answers right for the first time around but when
it is run for 2nd time onward it gives wrong answers only. I think it has to do sth with how my code is recursive. Please help me figure it out.
for example when i run count_bits(24) it gives the output 2 which is correct but when i run the same function again it would give 4 and then 6 and so on . I dont know what's wrong with this
My code.
dec_num = []
def count_bits(n):
def DecimalToBinary(n):
if n >= 1:
DecimalToBinary(n // 2)
dec_num.append( n % 2)
return dec_num
dec = DecimalToBinary(n)
return dec.count(1)
There is no need to create a list of digits if all you need is their sum. When possible, avoid creating mutable state in a recursive solution:
def count_bits(n):
if n > 0:
return n % 2 + count_bits(n // 2)
else:
return 0
That's a pretty natural translation of the obvious algorithm:
The sum of the bits in a number is the last bit plus the sum of the bits in the rest of the number.
Sometimes it's convenient to accumulate a result, which is best done by adding an accumulator argument. In some languages, that can limit stack usage, although not in Python which doesn't condense tail calls. All the same, some might find this more readable:
def count_bits(n, accum = 0):
if n > 0:
return count_bits(n // 2, accum + n % 2)
else:
return accum
In Python, a generator is a more natural control structure:
def each_bit(n):
while n > 0:
yield n % 2
n //= 2
def count_bits(n):
return sum(each_bit(n))
Of course, there are lots more ways to solve this problem.
That is because dec_num is outside the method, so it's reused at every call, put it inside
def count_bits(n):
dec_num = []
def DecimalToBinary(n):
if n >= 1:
DecimalToBinary(n // 2)
dec_num.append(n % 2)
return dec_num
dec = DecimalToBinary(n)
return dec.count(1)

Sum of 1st N natural numbers in O(no. of digits in N)

I'm trying to write a program to find sum of first N natural numbers i.e. 1 + 2 + 3 + .. + N modulo 1000000009
I know this can be done by using the formula N * (N+1) / 2 but I'm trying to find a sort of recursive function to calculate the sum.
I tried searching the web, but I didn't get any solution to this.
Actually, the problem here is that the number N can have upto 100000 digits.
So, here is what I've tried until now.
First I tried splitting the number into parts each of length 9, then convert them into integers so that I can perform arithmetic operations using the operators for integers.
For example, the number 52562372318723712 will be split into 52562372 & 318723712.
But I didn't find a way to manipulate these numbers.
Then again I tried to write a function as follows:
def find_sum(n):
# n is a string
if len(n) == 1:
# use the formula if single digit
return int(int(n[0]) * (int(n[0]) + 1) / 2)
# I'm not sure what to return here
# I'm expecting some manipulation with n[0]
# and a recursive call to the function itself
# I've also not used modulo here just for testing with smaller numbers
# I'll add it once I find a solution to this
return int(n[0]) * something + find_sum(n[1:])
I'm not able to find the something here.
Can this be solved like this?
or is there any other method to do so?
NOTE: I prefer a solution similar to the above function because I want to modify this function to meet my other requirements which I want to try myself before asking here. But if it is not possible, any other solution will also be helpful.
Please give me any hint to solve it.
Your best bet is to just use the N*(N+1)/2 formula -- but using it mod p. The only tricky part is to interpret division by 2 -- this had to be the inverse of 2 mod p. For p prime (or simply for p odd) this is very easy to compute: it is just (p+1)//2.
Thus:
def find_sum(n,p):
two_inv = (p+1)//2 #inverse of 2, mod p
return ((n%p)*((n+1)%p)*two_inv)%p
For example:
>>> find_sum(10000000,1000000009)
4550000
>>> sum(range(1,10000001))%1000000009
4550000
Note that the above function will fail if you pass an even number for p.
On Edit as #user11908059 observed, it is possible to dispense with multiplication by the modular inverse of 2. As an added benefit, this approach no longer depends on the modulus being odd:
def find_sum2(n,k):
if n % 2 == 0:
a,b = (n//2) % k, (n+1) % k
else:
a,b = n % k, ((n+1)//2) % k
return (a*b) % k

Why does this function return different values than it prints?

Beginner question - I'm trying to solve CodeAbbey's Problem #174, "Calculation of Pi", and so far I have written a function that accurately calculates the sidelengths of a regular Polygon with 6*N corners, thus approximating a circle.
In the code below, the function x(R,d) prints the correct values for "h" and "side" (compare the values given in the example on CodeAbbey), but when I ran my code through pythontutor, I saw that it returns slightly different values, for example 866025403784438700 instead of 866025403784438646 for the first value of h.
Can someone help me understand why this is?
As you can probably tell, I'm an amateur. I took the isqrt function from here, as the math.sqrt(x) method seems to give very imprecise results for large values of x
def isqrt(x):
# Returns the integer square root. This seems to be unproblematic
if x < 0:
raise ValueError('square root not defined for negative numbers')
n = int(x)
if n == 0:
return 0
a, b = divmod(n.bit_length(), 2)
x = 2**(a+b)
while True:
y = (x + n//x)//2
if y >= x:
return x
x = y
def x(R,d):
# given Radius and sidelength of initial polygon,
# this should return sidelength of new polygon.
h = isqrt(R**2 - d**2)
side = isqrt(d**2 + (R-h)**2)
print (h, side) # the values in this line are slightly
return (h, side) # different than the ones here. Why?
def approximate_pi(K,N):
R = int(10**K)
d = R // 2
for i in range(N):
d = (x(R,d)[1] // 2)
return int(6 * 2**(N) * d)
print (approximate_pi(18,4))
That's an artifact of Python Tutor. It's not something actually happening in your code.
From a very brief look at the Python Tutor source code, it looks like the Python execution backend is a slightly hacked-up, mostly standard CPython instance with debug instrumentation through bdb, but the visualization is in Javascript. The printed output comes from the Python standard output, but the visualization goes through Javascript, and the Python integers get converted to Javascript Number values, losing precision because Number is 64-bit floating point.
It has to do with rounding to the nearest integer.
In your function divmod(n.bit_length(), 2), try to change 2 to 2.0, it will give similar value to what you saw on their plateform.

Random number function python that includes 1?

I am new to Python and am trying to create a program for a project- firstly, I need to generate a point between the numbers 0-1.0, including 0 and 1.0 ([0, 1.0]). I searched the python library for functions (https://docs.python.org/2/library/random.html) and I found this function:
random.random()
This will return the next random floating point number in the range [0.0, 1.0). This is a problem, since it does not include 1. Although the chances of actually generating a 1 are very slim anyway, it is still important because this is a scientific program that will be used in a larger data collection.
I also found this function:
rand.randint
This will return an integer, which is also a problem.
I researched on the website and previously asked questions and found that this function:
random.uniform(a, b)
will only return a number that is greater than or equal to a and less than b.
Does anyone know how to create a random function on python that will include [0, 1.0]?
Please correct me if I was mistaken on any of this information. Thank you.
*The random numbers represent the x value of a three dimensional point on a sphere.
Could you make do with something like this?
random.randint(0, 1000) / 1000.0
Or more formally:
precision = 3
randomNumber = random.randint(0, 10 ** precision) / float(10 ** precision)
Consider the following function built on top of random.uniform. I believe that the re-sampling approach should cause all numbers in the desired interval to appear with equal probability, because the probability of returning candidate > b is 0, and originally all numbers should be equally likely.
import sys
import random
def myRandom(a, b):
candidate = uniform.random(a, b + sys.float_info.epsilon)
while candidate > b:
candidate = uniform.random(a, b + sys.float_info.epsilon)
return candidate
As gnibbler mentioned below, for the general case, it may make more sense to change both the calls to the following. Note that this will only work correctly if b > 0.
candidate = uniform.random(a, b*1.000001)
Try this:
import random
random.uniform(0.0, 1.0)
Which will, according to the documentation [Python 3.x]:
Return a random floating point number N such that a <= N <= b for a <= b and b <= N <= a for b < a.
Notice that the above paragraph states that b is in fact included in the range of possible values returned by the function. However, beware of the second part (emphasis mine):
The end-point value b may or may not be included in the range depending on floating-point rounding in the equation a + (b-a) * random().
For floating point numbers you can use numpy's machine limits for floats class to get the smallest possible value for 64bit or 32bit floating point numbers. In theory, you should be able to add this value to b in random.uniform(a, b) making 1 inclusive in your generator:
import numpy
import random
def randomDoublePrecision():
floatinfo = numpy.finfo(float)
epsilon = floatinfo.eps
a = random.uniform(0, 1 + eps)
return a
This assumes that you are using full precision floating point numbers for your number generator. For more info read this Wikipedia article.
Would it be just:
list_rnd=[random.random() for i in range(_number_of_numbers_you_want)]
list_rnd=[item/max(list_rnd) for item in list_rnd]
Generate a list of random numbers and divide it by its max value. The resulting list still flows uniform distribution.
I've had the same problem, this should help you.
a: upper limit,
b: lower limit, and
digit: digit after comma
def konv_des (bin,a,b,l,digit):
des=int(bin,2)
return round(a+(des*(b-a)/((2**l)-1)),digit)
def rand_bin(p):
key1 = ""
for i in range(p):
temp = str(random.randint(0, 1))
key1 += temp
return(key1)
def rand_chrom(a,b,digit):
l = 1
eq=False
while eq==False:
l += 1
eq=2**(l-1) < (b-a)*(10**digit) and (b-a)*(10**digit) <= (2**l)-1
return konv_des(rand_bin(l),a,b,l,digit)
#run
rand_chrom(0,1,4)

Categories

Resources