如何创建将 0 和 1 数组转换为浮点数的函数?[关闭]

How to create function that translates an array of 0 and 1s into a float? [closed]

提问人:mitas1c 提问时间:5/1/2023 更新时间:5/1/2023 访问量:64

问:


想改进这个问题吗?通过编辑这篇文章添加详细信息并澄清问题。

7个月前关闭。

我正在尝试创建一个将数组作为参数的函数,该数组表示数字,但在二进制中,我希望此函数返回一个数字。

我可以将任何数字转换为二进制,但是我无法弄清楚如何从二进制中获取浮点数。

例如,4.8 是 [0, 1, 0, 0, 1, 1, 0, 0],但是当我像这样调用函数 binaryToFloat([0, 1, 0, 0, 1, 1, 0, 0]) 时,它返回 5.2 而不是 4.8。

但是,我只能使用下面提供的功能。 谁能帮我?

from typing import List, Callable

def bitNot(bit:int) -> int:
    return 1 - bit

def bitAnd(bit1:int, bit2:int) -> int:
    return bit1 * bit2

def bitOr(bit1:int, bit2:int) -> int:
    return max(bit1, bit2)

def bitXor(bit1:int, bit2:int) -> int:
    return bitOr(bit1, bit2) - bitAnd(bit1, bit2)

def map_array(function, array):
    """Použije funkci na každý prvek pole."""
    result = []
    for el in array:
        result += [function(el)]
    return result 

def zipArray(arr1: List, arr2: List) -> List:
    result: List = []
    for i in range(len(arr1)):
        result += [[arr1[i], arr2[i]]]
    return result
"""
>>> zipArray([1, 2, 3], [4, 5, 6])
[[1, 4], [2, 5], [3, 6]]
"""
def mapTwoArrays(func: Callable, arr1: List, arr2: List) -> List:
    
    def mapFunc(pair):
        return func(pair[0], pair[1])
    
    return map_array(mapFunc, zipArray(arr1, arr2))
    
def add(num: int, num2: int) -> int:
    return num + num2
"""
>>> mapTwoArrays(add, [1, 2, 3], [4, 5, 6])
[5, 7, 9]
"""

def bitArrayAnd(arr1: List, arr2: List) -> List:
    return mapTwoArrays(bitAnd, arr1, arr2)

def bitArrayOr(arr1: List, arr2: List) -> List:
    return mapTwoArrays(bitOr, arr1, arr2)

def bitArrayXor(arr1: List, arr2: List) -> List:
    return mapTwoArrays(bitXor, arr1, arr2)

def bitArrayLeftShift(arr: List, n: int) -> List:  
    return arr + (n * [0])

def bitArrayNot(arr: List) -> List:
    return map_array(bitNot, arr)

"""
rekurze verze
def bitArrayRightShift(arr: List, n: int) -> List:
    if n == 0:
        return arr
    else:
       return bitArrayRightShift(arr[:-1], n -1)
"""
   
def bitArrayRightShift(arr: List, n: int) -> List:
    return arr[:len(arr) - n]

def fillZeroes(arr: List, n: int) -> List:
    return ([0] * n) + arr

def alignSize(arr: List, n: int) -> List:
    return fillZeroes(arr, n - len(arr))

#pouze pomocí bitových operaci
def setBitOn(arr: List, i: int) -> List:
    res: List = alignSize(bitArrayLeftShift([1], i), len(arr))
    return bitArrayOr(arr, res)

def setBitOff(arr: List, i: int) -> List:
    res: List = alignSize(bitArrayLeftShift([1], i), len(arr))
    return map_array(bitNot,res)

def getBit(arr: List, i: int) -> List:
    res: List = bitArrayRightShift(arr, i)
    mask: List = alignSize([1], len(res))
    return bitArrayAnd(res,mask)

#reprezentace nezáporných čísel v dvojkove soustave
def unsignedIntToBytes(num: int) -> List:
    result: List = []
    while num != 0:
        bit: int = num % 2
        result = [bit] + result
        num = num // 2
    return result

"""
>>> unsignedIntToBytes(5)
[1, 0, 1]
"""

def bitesToUnsignedInt(arr: List) -> int:
    integer = 0
    for i in range(len(arr)):
        if arr[i] == 1:
            integer += 2 ** (len(arr) - i - 1)
    return integer
"""
>>> bitesToUnsignedInt([1, 0, 1])
5
"""

#cela cisla v binary
def numToBytes(num: int, size: int) -> List:
    if num >= 0:
        arr: List = unsignedIntToBytes(num)
        fillSize = size - len(arr)
        if fillSize <= 0:
            raise ValueError(f'SIze of arr, to small, Missing {-fillSize+1} bit(s)')
        return [0] * (size - len(arr)) + arr
    else:
        return bitArrayNot(numToBytes(-num - 1, size))
"""
>>> numToBytes(8, 8)
[0, 0, 0, 0, 1, 0, 0, 0]
>>> numToBytes(-8, 8)
[1, 1, 1, 1, 1, 0, 0, 0]
"""
  
def bytesToNum(arr: List) -> int:
    signBit: int = arr[0]
    if signBit == 0:
        return bitesToUnsignedInt(arr)
    else:
        return -(bytesToNum(bitArrayNot(arr)) + 1)
"""
>>> bytesToNum([0, 0, 0, 0, 1, 0, 0, 0])
8
>>> bytesToNum([1, 1, 1, 1, 1, 0, 0, 0])
-8
"""      

def nativeSetBitOn(num: int, i: int) -> int:
    res: int = 1 << i
    return num | res

def nativeSetBitOff(num: int, i: int) -> int:
    res: int = ~(1 << i)
    return num & res
"""
>>> native_set_bit_off(8, 3)
0
>>> native_set_bit_off(-1, 2)
-5
"""
def nativeGetBit(n: int, i:int) -> int:
    res: int = n >> i
    return res & n
"""
>>> nativeGetBit(8, 3)
1
"""
def nativeNumberToBitArray(num: int, size:int) -> List:
    bit_array = []
    for i in range(size-1, -1, -1):
        bit = (num >> i) & 1
        bit_array.append(bit)
    return bit_array
"""
>>> nativeNumberToBitArray(5, 8)
[0, 0, 0, 0, 0, 1, 0, 1]
>>> nativeNumberToBitArray(-1, 8)
[1, 1, 1, 1, 1, 1, 1, 1]
"""
def getFirst(n:int) -> int:
    return n & 1
"""
>>> getFirst(9)
1
"""

def getRest(n:int) -> int:
    return n >> 1
"""
>>> getRest(9)
4
"""

def nativeNumberToBitArray2(num: int, size:int) -> List:
    """Převede číslo na seznam bitů. Používá native_get_bit."""
    bit_array = []
    for i in range(size-1, -1, -1):
        bit_array.append(nativeGetBit(num, i) & 1)
    return bit_array

"""
>>> nativeNumberToBitArray2(5, 8)
[0, 0, 0, 0, 0, 1, 0, 1]
>>> nativeNumberToBitArray2(-1, 8)
[1, 1, 1, 1, 1, 1, 1, 1]
"""

DAY_BIT_COUNT = 5
MONTH_BIT_COUNT = 4
YEAR_BIT_COUNT = 7

def encodeDate(date: List) -> int:
    day = date[0] << (MONTH_BIT_COUNT + YEAR_BIT_COUNT)
    month = date[1] << YEAR_BIT_COUNT
    year = (date[2] - 2000) & ((1 << YEAR_BIT_COUNT) - 1)
    return day | month | year

def decodeDate(date: int) -> List:
    year = (date & ((1 << YEAR_BIT_COUNT) - 1)) + 2000
    month = (date >> YEAR_BIT_COUNT) & ((1 << MONTH_BIT_COUNT) - 1)
    day = date >> (YEAR_BIT_COUNT + MONTH_BIT_COUNT)
    return [day, month, year]

#zápočet funkce co zakoduje a dekoduje zpět
#je to zápočet

#Rozšířit o rok
#[27,4,2033]


def floatToBinary(num: float, size: int):
    int_part = int(num)
    float_part = num - int_part
    int_binary = numToBytes(int_part, size)  # assuming 32-bit integers
    float_binary = []
    for i in range(size):
        float_part *= 2
        bit = int(float_part)
        float_binary.append(bit)
        float_part -= bit
        
    return int_binary + float_binary

def floatToBytes(num: float) -> List[int]:
    # Extract sign, exponent, and significand
    sign = 0 if num >= 0 else 1
    num = abs(num)
    exponent = 0
    while num >= 2.0:
        num /= 2.0
        exponent += 1
    while num < 1.0:
        num *= 2.0
        exponent -= 1
    significand = num - 1.0

    # Convert sign, exponent, and significand to binary
    sign_bits = [sign]
    exponent_bits = numToBytes(exponent + 127, 8)
    significand_bits = unsignedIntToBytes(int(significand * (1 << 23)))

    # Combine sign, exponent, and significand bits
    return sign_bits + exponent_bits + significand_bits

def binaryToFloat(bits: List[int]) -> float:
    whole_part = 0
    fractional_part = 0
    for i in range(len(bits)):
        if i < 4:
            whole_part += bits[i] * (2 ** (3 - i))
        else:
            fractional_part += bits[i] * (2 ** (3 - (i - 4)))
    return whole_part + (fractional_part / 10)

print(floatToBinary(4.8,4))
print(binaryToFloat([0, 1, 0, 0, 1, 1, 0, 0])) #Should be 4.8
python-3.x 浮点 二进制 二进制数据

评论

3赞 Kelly Bundy 5/1/2023
“4.8 是 [0, 1, 0, 0, 1, 1, 0, 0]” - 怎么会这样?
1赞 Kelly Bundy 5/1/2023
没关系,这对我来说代码太多了,无论如何都无法研究这个......
1赞 B Remmelzwaal 5/1/2023
当只有一个函数是问题时,为什么要发布所有代码?
0赞 CtrlZ 5/1/2023
你 [0, 1, 0, 0, 1, 1, 0, 0] == 4.8 的职权范围是什么?
0赞 B Remmelzwaal 5/1/2023
此外,从外观上看,这些不是浮点数,而是固定点值。

答:

1赞 B Remmelzwaal 5/1/2023 #1

问题是您的小数部分计算不正确。小数部分的每个位代表 2 的幂倒数,即 1/2、1/4、1/8 等。

凭借这些固定点的精度,您可以获得的最佳值为 4.75,因为二进制中的 0.8 是 0.1100110011...

def binaryToFloat(bits: List[int]) -> float:
    whole_part = 0
    fractional_part = 0
    for i in range(len(bits)):
        if i < 4:
            whole_part += bits[i] * (2 ** (3 - i))
        else:
            fractional_part += bits[i] / (2 ** (i - 3))
    return whole_part + fractional_part

print(binaryToFloat([0, 1, 0, 0, 1, 1, 0, 0]))

评论

0赞 Eric Postpischil 5/1/2023
4.8125 在基数点后有四位(作为二进制 100.1101)的定点表示,比 4.75 更接近 4.8。