Signed float to hexadecimal number - python-3.x

How to convert float to a specific format in hexadecimal:
1 bit for sign, 15 bit for the integer value, and the rest 16 bits for values after the decimal point.
Example output should be ffff587a for -0.6543861, fff31a35 for -12.897631, 006bde10 for 107.8674316, 003bd030 for 59.8132324
I have written a program that can do the unsigned conversion, I am stuck at the signed part. Could anyone guide me on how I can achieve this in a very compact way?
def convert(num):
binary2 = ""
Int = int(num)
fract = num - Int
binary = '{:16b}'.format(Int & 0b1111111111111111)
for i in range (16):
fract *= 2
fract_bit = int(fract)
if fract_bit == 1:
fract -= fract_bit
binary2 += '1'
else:
binary2 += '0'
return int(binary + binary2, 2)
value = 107.867431640625
x = convert(value)
hex(x)
output: 0x6bde10

This is simply the Q16.16 fixed-point format. To convert a floating-point number to this format, simply multiply it by 216 (in Python, 1<<16 or 65536) and convert the product to an integer:
y = int(x * (1<<16))
To show its 32-bit two’s complement representation, add 232 if it is negative and then convert it to hexadecimal:
y = hex(y + (1<<32 if y < 0 else 0))
For example, the following prints “0xfff31a35”:
#!/usr/bin/python
x=-12.897631
y = int(x * (1<<16))
y = hex(y + (1<<32 if y < 0 else 0))
print(y)
This conversion truncates. If you want rounding, you can add .5 inside the int or you can add additional code for other types of rounding. You may also want to add code to handle overflows.

Related

fmt::format how to always print first n non-zero digits with leading zeroes

Given three floating point numbers
a = 1.0
b = 1.23456
c = 1.23456e-12
How can I always print the first n non-zero digits, with leading zeroes, if required. Desired output for n=6:
1.00000
1.23456
0.00000000000123456
I tried fmt::format("{:.6f"}", number) but this returns 0.00000 in the last case.
There is no built-in way of doing this but you could do it in several steps:
Format using the exponent notation (e).
Extract the exponent.
Format using the fixed notation (f) adjusting the precision to account for the exponent.
For example:
#include <fmt/core.h>
void print(double n) {
auto s = fmt::format("{:e}", n);
auto exp = atoi(s.substr(s.find('e') + 1).c_str());
int precision = 6;
if (exp < 0) precision -= exp;
fmt::print("{:.{}f}\n", n, precision - 1);
}
int main() {
print(1.0);
print(1.23456);
print(1.23456e-12);
}
This prints:
1.00000
1.23456
0.00000000000123456
https://godbolt.org/z/16n8s7TG3

Python Bit Summation Algorithm

I am trying to implement a function that will be used to judge whether a generator's output is continuous. The method I am gravitating towards is to iterate through the generator. For each value, I right justify the bits of the value (disregarding the 0b), count the number of ones, and shift the number of ones.
#!/usr/bin/python3
from typing import Tuple
def find_bit_sum(top: int, pad_length: int) -> int :
"""."""
return pad_length * (top + 1)
def find_pad_length(top: int) -> int :
"""."""
return len(bin(top)) - 2 # -"0b"
def guess_certain(top: int, pad_length: int) -> Tuple[int, int, int] :
"""."""
_both: int = find_bit_sum(top, pad_length)
_ones: int = sum(sum(int(_i_in) for _i_in in bin(_i_out)[2 :]) for _i_out in range(1, top + 1))
return _both - _ones, _ones, _both # zeros, ones, sum
def guess(top: int, pad_length: int) -> Tuple[int, int, int] : # zeros then ones then sum
"""."""
_bit_sum: int = find_bit_sum(top, pad_length) # number of bits in total
_zeros: int = _bit_sum # ones are deducted
_ones: int = 0 # _bit_sum - _zeros
# detect ones
for _indexed in range(pad_length) :
_ones_found: int = int(top // (2 ** (_indexed + 1))) # HELP!!!
_zeros -= _ones_found
_ones += _ones_found
#
return _zeros, _ones, _bit_sum
def test_the_guess(max_value: int) -> bool : # the range is int [0, max_value + 1)
pad: int = find_pad_length(max_value)
_zeros0, _ones0, _total0 = guess_certain(max_value, pad)
_zeros1, _ones1, _total1 = guess(max_value, pad)
return all((
_zeros0 == _zeros1,
_ones0 == _ones1,
_total0 == _total1
))
if __name__ == '__main__' : # should produce a lot of True
for x in range(3000) :
print(test_the_guess(x))
For the life of me, I cannot make guess() agree with guess_certain(). The time complexity of guess_certain() is my problem: it works for small ranges [0, top], but one can forget 256-bit numbers (tops). The find_bit_sum() function works perfectly. The find_pad_length() function also works.
top // (2 ** (_indexed + 1))
I've tried 40 or 50 variations of the guess() function. It has thoroughly frustrated me. The guess() function is probabilistic. In its finished state: if it returns False, then the Generator definitely isn't producing every value in range(top + 1); however, if it returns True, then the Generator could be. We already know that the generator range(top + 1) is continuous because it does produce each number between 0 and top inclusively; so, test_the_guess() should be returning True.
I sincerely do apologise for the chaotic explanation. If you have anny questions, please don't hesitate to ask.
I adjusted your ones_found assignment statement to account for the number of powers of two per int(top // (2 ** (_indexed + 1))), as well as a additional "rollover" ones that occur before the next power of two. Here is the resulting statement:
_ones_found: int = int(top // (2 ** (_indexed + 1))) * (2 ** (_indexed)) + max(0, (top % (2 ** (_indexed + 1))) - (2 ** _indexed) + 1)
I also took the liberty of converting the statement to bitwise operators for both clarity and speed, as shown below:
_ones_found: int = ((top >> _indexed + 1) << _indexed) + max(0, (top & (1 << _indexed + 1) - 1) - (1 << _indexed) + 1)

How to find the lexicographically smallest string by reversing a substring?

I have a string S which consists of a's and b's. Perform the below operation once. Objective is to obtain the lexicographically smallest string.
Operation: Reverse exactly one substring of S
e.g.
if S = abab then Output = aabb (reverse ba of string S)
if S = abba then Output = aabb (reverse bba of string S)
My approach
Case 1: If all characters of the input string are same then output will be the string itself.
Case 2: if S is of the form aaaaaaa....bbbbbb.... then answer will be S itself.
otherwise: Find the first occurence of b in S say the position is i. String S will look like
aa...bbb...aaaa...bbbb....aaaa....bbbb....aaaaa...
|
i
In order to obtain the lexicographically smallest string the substring that will be reversed starts from index i. See below for possible ending j.
aa...bbb...aaaa...bbbb....aaaa....bbbb....aaaaa...
| | | |
i j j j
Reverse substring S[i:j] for every j and find the smallest string.
The complexity of the algorithm will be O(|S|*|S|) where |S| is the length of the string.
Is there a better way to solve this problem? Probably O(|S|) solution.
What I am thinking if we can pick the correct j in linear time then we are done. We will pick that j where number of a's is maximum. If there is one maximum then we solved the problem but what if it's not the case? I have tried a lot. Please help.
So, I came up with an algorithm, that seems to be more efficient that O(|S|^2), but I'm not quite sure of it's complexity. Here's a rough outline:
Strip of the leading a's, storing in variable start.
Group the rest of the string into letter chunks.
Find the indices of the groups with the longest sequences of a's.
If only one index remains, proceed to 10.
Filter these indices so that the length of the [first] group of b's after reversal is at a minimum.
If only one index remains, proceed to 10.
Filter these indices so that the length of the [first] group of a's (not including the leading a's) after reversal is at a minimum.
If only one index remains, proceed to 10.
Go back to 5, except inspect the [second/third/...] groups of a's and b's this time.
Return start, plus the reversed groups up to index, plus the remaining groups.
Since any substring that is being reversed begins with a b and ends in an a, no two hypothesized reversals are palindromes and thus two reversals will not result in the same output, guaranteeing that there is a unique optimal solution and that the algorithm will terminate.
My intuition says this approach of probably O(log(|S|)*|S|), but I'm not too sure. An example implementation (not a very good one albeit) in Python is provided below.
from itertools import groupby
def get_next_bs(i, groups, off):
d = 1 + 2*off
before_bs = len(groups[i-d]) if i >= d else 0
after_bs = len(groups[i+d]) if i <= d and len(groups) > i + d else 0
return before_bs + after_bs
def get_next_as(i, groups, off):
d = 2*(off + 1)
return len(groups[d+1]) if i < d else len(groups[i-d])
def maximal_reversal(s):
# example input: 'aabaababbaababbaabbbaa'
first_b = s.find('b')
start, rest = s[:first_b], s[first_b:]
# 'aa', 'baababbaababbaabbbaa'
groups = [''.join(g) for _, g in groupby(rest)]
# ['b', 'aa', 'b', 'a', 'bb', 'aa', 'b', 'a', 'bb', 'aa', 'bbb', 'aa']
try:
max_length = max(len(g) for g in groups if g[0] == 'a')
except ValueError:
return s # no a's after the start, no reversal needed
indices = [i for i, g in enumerate(groups) if g[0] == 'a' and len(g) == max_length]
# [1, 5, 9, 11]
off = 0
while len(indices) > 1:
min_bs = min(get_next_bs(i, groups, off) for i in indices)
indices = [i for i in indices if get_next_bs(i, groups, off) == min_bs]
# off 0: [1, 5, 9], off 1: [5, 9], off 2: [9]
if len(indices) == 1:
break
max_as = max(get_next_as(i, groups, off) for i in indices)
indices = [i for i in indices if get_next_as(i, groups, off) == max_as]
# off 0: [1, 5, 9], off 1: [5, 9]
off += 1
i = indices[0]
groups[:i+1] = groups[:i+1][::-1]
return start + ''.join(groups)
# 'aaaabbabaabbabaabbbbaa'
TL;DR: Here's an algorithm that only iterates over the string once (with O(|S|)-ish complexity for limited string lengths). The example with which I explain it below is a bit long-winded, but the algorithm is really quite simple:
Iterate over the string, and update its value interpreted as a reverse (lsb-to-msb) binary number.
If you find the last zero of a sequence of zeros that is longer than the current maximum, store the current position, and the current reverse value. From then on, also update this value, interpreting the rest of the string as a forward (msb-to-lsb) binary number.
If you find the last zero of a sequence of zeros that is as long as the current maximum, compare the current reverse value with the current value of the stored end-point; if it is smaller, replace the end-point with the current position.
So you're basically comparing the value of the string if it were reversed up to the current point, with the value of the string if it were only reversed up to a (so-far) optimal point, and updating this optimal point on-the-fly.
Here's a quick code example; it could undoubtedly be coded more elegantly:
function reverseSubsequence(str) {
var reverse = 0, max = 0, first, last, value, len = 0, unit = 1;
for (var pos = 0; pos < str.length; pos++) {
var digit = str.charCodeAt(pos) - 97; // read next digit
if (digit == 0) {
if (first == undefined) continue; // skip leading zeros
if (++len > max || len == max && reverse < value) { // better endpoint found
max = len;
last = pos;
value = reverse;
}
} else {
if (first == undefined) first = pos; // end of leading zeros
len = 0;
}
reverse += unit * digit; // update reverse value
unit <<= 1;
value = value * 2 + digit; // update endpoint value
}
return {from: first || 0, to: last || 0};
}
var result = reverseSubsequence("aaabbaabaaabbabaaabaaab");
document.write(result.from + "→" + result.to);
(The code could be simplified by comparing reverse and value whenever a zero is found, and not just when the end of a maximally long sequence of zeros is encountered.)
You can create an algorithm that only iterates over the input once, and can process an incoming stream of unknown length, by keeping track of two values: the value of the whole string interpreted as a reverse (lsb-to-msb) binary number, and the value of the string with one part reversed. Whenever the reverse value goes below the value of the stored best end-point, a better end-point has been found.
Consider this string as an example:
aaabbaabaaabbabaaabaaab
or, written with zeros and ones for simplicity:
00011001000110100010001
We iterate over the leading zeros until we find the first one:
0001
^
This is the start of the sequence we'll want to reverse. We will start interpreting the stream of zeros and ones as a reversed (lsb-to-msb) binary number and update this number after every step:
reverse = 1, unit = 1
Then at every step, we double the unit and update the reverse number:
0001 reverse = 1
00011 unit = 2; reverse = 1 + 1 * 2 = 3
000110 unit = 4; reverse = 3 + 0 * 4 = 3
0001100 unit = 8; reverse = 3 + 0 * 8 = 3
At this point we find a one, and the sequence of zeros comes to an end. It contains 2 zeros, which is currently the maximum, so we store the current position as a possible end-point, and also store the current reverse value:
endpoint = {position = 6, value = 3}
Then we go on iterating over the string, but at every step, we update the value of the possible endpoint, but now as a normal (msb-to-lsb) binary number:
00011001 unit = 16; reverse = 3 + 1 * 16 = 19
endpoint.value *= 2 + 1 = 7
000110010 unit = 32; reverse = 19 + 0 * 32 = 19
endpoint.value *= 2 + 0 = 14
0001100100 unit = 64; reverse = 19 + 0 * 64 = 19
endpoint.value *= 2 + 0 = 28
00011001000 unit = 128; reverse = 19 + 0 * 128 = 19
endpoint.value *= 2 + 0 = 56
At this point we find that we have a sequence of 3 zeros, which is longer that the current maximum of 2, so we throw away the end-point we had so far and replace it with the current position and reverse value:
endpoint = {position = 10, value = 19}
And then we go on iterating over the string:
000110010001 unit = 256; reverse = 19 + 1 * 256 = 275
endpoint.value *= 2 + 1 = 39
0001100100011 unit = 512; reverse = 275 + 1 * 512 = 778
endpoint.value *= 2 + 1 = 79
00011001000110 unit = 1024; reverse = 778 + 0 * 1024 = 778
endpoint.value *= 2 + 0 = 158
000110010001101 unit = 2048; reverse = 778 + 1 * 2048 = 2826
endpoint.value *= 2 + 1 = 317
0001100100011010 unit = 4096; reverse = 2826 + 0 * 4096 = 2826
endpoint.value *= 2 + 0 = 634
00011001000110100 unit = 8192; reverse = 2826 + 0 * 8192 = 2826
endpoint.value *= 2 + 0 = 1268
000110010001101000 unit = 16384; reverse = 2826 + 0 * 16384 = 2826
endpoint.value *= 2 + 0 = 2536
Here we find that we have another sequence with 3 zeros, so we compare the current reverse value with the end-point's value, and find that the stored endpoint has a lower value:
endpoint.value = 2536 < reverse = 2826
so we keep the end-point set to position 10 and we go on iterating over the string:
0001100100011010001 unit = 32768; reverse = 2826 + 1 * 32768 = 35594
endpoint.value *= 2 + 1 = 5073
00011001000110100010 unit = 65536; reverse = 35594 + 0 * 65536 = 35594
endpoint.value *= 2 + 0 = 10146
000110010001101000100 unit = 131072; reverse = 35594 + 0 * 131072 = 35594
endpoint.value *= 2 + 0 = 20292
0001100100011010001000 unit = 262144; reverse = 35594 + 0 * 262144 = 35594
endpoint.value *= 2 + 0 = 40584
And we find another sequence of 3 zeros, so we compare this position to the stored end-point:
endpoint.value = 40584 > reverse = 35594
and we find it has a smaller value, so we replace the possible end-point with the current position:
endpoint = {position = 21, value = 35594}
And then we iterate over the final digit:
00011001000110100010001 unit = 524288; reverse = 35594 + 1 * 524288 = 559882
endpoint.value *= 2 + 1 = 71189
So at the end we find that position 21 gives us the lowest value, so it is the optimal solution:
00011001000110100010001 -> 00000010001011000100111
^ ^
start = 3 end = 21
Here's a C++ version that uses a vector of bool instead of integers. It can parse strings longer than 64 characters, but the complexity is probably quadratic.
#include <vector>
struct range {unsigned int first; unsigned int last;};
range lexiLeastRev(std::string const &str) {
unsigned int len = str.length(), first = 0, last = 0, run = 0, max_run = 0;
std::vector<bool> forward(0), reverse(0);
bool leading_zeros = true;
for (unsigned int pos = 0; pos < len; pos++) {
bool digit = str[pos] - 'a';
if (!digit) {
if (leading_zeros) continue;
if (++run > max_run || run == max_run && reverse < forward) {
max_run = run;
last = pos;
forward = reverse;
}
}
else {
if (leading_zeros) {
leading_zeros = false;
first = pos;
}
run = 0;
}
forward.push_back(digit);
reverse.insert(reverse.begin(), digit);
}
return range {first, last};
}

Create number sequence of length x with only difference of 1 bit in successive numbers

Was asked this Amazon Telephonic Interview Round 1
So for Length = 1
0 1 (0 1)
Length = 2
00 01 11 10 (0, 1, 3, 2)
and so on
write function for length x that returns numbers in digit(base 10) form
That's called gray code, there are several different kinds, some of which are easier to construct than others. The wikipedia article shows a very simple way to convert from binary to gray code:
unsigned int binaryToGray(unsigned int num)
{
return (num >> 1) ^ num;
}
Using that, you only have to iterate over all numbers of a certain size, put them through that function, and print them however you want.
This is one way to do it:
int nval = (int)Math.Pow(2 , n);
int divisor = nval/2;
for (int i = 0; i < nval; i++)
{
int nb =(int) (i % divisor);
if ( nb== 2) Console.WriteLine(i + 1);
else if (nb == 3) Console.WriteLine(i - 1);
else Console.WriteLine(i);
}

Converting decimal to specific scientific notation format

I'm trying to convert decimal to a specific scientific notation format:
-2.802479940 ==> -.2802479940E+01
3.796137791 ==> 0.3796137791E+01
And so on. Basically, No leading zero on negative numbers and a leading zero
on positive numbers. I've been able to print out in the big E scientific notation
but have no idea how to force the leading part to be a '-' or a '0' only.
This is kind of ugly (there aren't any built-in string-formatting options for it as far as I know), but it should do what you want it to do:
import re
nums = [-2.802479940, 3.796137791, -0.012, 0.035, 0, 100, -200]
decimal_digits = 10
for n in nums:
num = ('{:.'+str(decimal_digits-1)+'E}').format(n)
# increment exponent
exp_search = re.search(r'E(\+|-)\d+', num).group()
sign = exp_search[1]
exp = int(exp_search[1:])
new_exp = exp + 1
exponent = 'E'+sign+'{:02}'.format(abs(new_exp))
# move decimal place over
sig_search = re.search(r'-?\d\.\d+', num).group()
stripped = sig_search.replace('.', '')
if stripped[0] == '-':
significand = stripped.replace('-', '-.')
else:
significand = '0.' + stripped
# glue significand and exponent back together
new_num = significand + exponent
print('{:>20}{:>20}'.format(num, new_num))
assert float(num) == float(new_num)
Output:
-2.802479940E+00 -.2802479940E+01
3.796137791E+00 0.3796137791E+01
-1.200000000E-02 -.1200000000E-01
3.500000000E-02 0.3500000000E-01
0.000000000E+00 0.0000000000E+01
1.000000000E+02 0.1000000000E+03
-2.000000000E+02 -.2000000000E+03
This doesn't perform any arithmetic, just string operations, so it shouldn't introduce any issues with floating-point representations or whatever.
Here's C code to do what you want:
void numfmt(double d, char* buf) {
int exp=0;
int cont=1;
char sign = '0';
if (d < 0) {
sign = '-';
d = -d;
}
while(cont) {
if (d >= 1.0) {
exp ++;
d /= 10.0;
} else if (d < 0.1) {
exp --;
d *= 10.0;
} else
cont = 0;
}
sprintf(buf,"%12.10fE%+03d",d,exp);
*buf = sign;
}
To convert any number into scientific notation you need to know two things, the exponent and the decimal part. like this: Number = Dec E exponent (or Number = Dec * 10^exponent)
Log10() function will be really important then, cause it will give you the exact exponent of Number! Then to get the exponent you have this relation:
exponent = log10(Number/Dec)
but not knowing the Dec part, we will simplify into this relation:
exponent = log10(Number)
this will not give the integer exponent, only the exponent for which 1/10^exponent = Number. To get the right integer exponent you will need to get the first lowest integer with the floor() function.
That's why you'll need to change the relation to:
exponent = int(floor(log10(Number))) # using int will convert any floating value into an integer exponent
Then using this exponent you could easily find the decimal part with the relation:
Dec = Number / 10^exponent
Now you have a way to change any number* into scientific notation, if you need to have a leading zero, you then just have to decrement the exponent ^^
* Log(x) is defined on R*+ so if you have a negative number you must convert it into a positive one before passing it as an argument to log10(), and if the number is 0, then you should make an exception (return dec = 0 and exponent = 0)
this is an example of code in python:
Decompose(originalvalue):
calcul = originalvalue;
if (originalvalue != 0.0):
if (originalvalue < 0):
calcul = -calcul;
exponent = int(floor(log10(calcul))); # get the integer exponent
value = originalvalue / 10.0**exponent; # get scientific decimal part
# then to have a leading zero, you just have to verifiy if dec >= 1 or not, and in this case, modify the value and exponent to eliminate it.
if (value >= 1):
value *= 10**-1
exponent += 1
else:
exponent = 0;
value = 0.0;
return [value, exponent];
Here is a solution I came up with, having the same problem.
def converter(number):
number_str = '{:.14e}'.format(number)
number_split = number_str.split('.')
int_part = number_split[0]
exp_part = number_split[1][-3:]
dec_part = number_split[1][:-6]
int_part_numeric = int(int_part)
if number == 0:
return '0.000000000000E+00'
if int_part_numeric == 0:
sign = '0'
new_exp_part = exp_part
new_dec_part = dec_part
elif int_part_numeric < 0:
sign = '-'
new_exp_part = '{:+03d}'.format(int(exp_part) + 1)
new_dec_part = int_part.strip('-') + dec_part[:-1]
elif int_part_numeric > 0:
sign = '0'
new_exp_part = '{:+03d}'.format(int(exp_part) + 1)
new_dec_part = int_part + dec_part[:-1]
return sign + '.' + new_dec_part + 'E' + new_exp_part
It could probably be simplified a bit though...

Resources