处理DataWeave中的负数十六进制。

huangapple go评论60阅读模式
英文:

Handling Negative Numbers in Hex in DataWeave

问题

I am working on retiring a Python Kafka Consumer to use Mule runtime instead.

我正在准备停用Python Kafka消费者,改用Mule运行时。

I have ran into a blocker with DataWeave and bitwise operators, specifically how to handle negative hex numbers.

我在DataWeave和位运算符方面遇到了一个障碍,具体来说是如何处理负十六进制数。

Currently, my Kafka/Debezium producer is providing the following value +PB34g== which should decode to -118.458398.

目前,我的Kafka/Debezium生产者提供了以下值 +PB34g==,它应该解码为 -118.458398

With Python I can use Two's Complement to shift and convert to negative. But, I haven't found a comparable DataWeave solution.

使用Python,我可以使用二进制补码进行移位和转换为负数。但是,我还没有找到一个类似的DataWeave解决方案。

We decode the Base64 value with this function, and then convert to integer with the function below.

我们使用这个函数解码Base64值,然后使用下面的函数将其转换为整数。

I can handle this in a Java class, but would prefer to use DataWeave if possible.

我可以在Java类中处理这个问题,但如果可能的话,我更愿意使用DataWeave。

I have the following DataWeave to convert from Base64 to a number. I have found this article where custom bitwise functions were created, but they did not handle negative values.

我有以下DataWeave来将Base64转换为数字。我找到了这篇文章,其中创建了自定义位运算函数,但它们没有处理负数值。

英文:

I am working on retiring a Python Kafka Consumer to use Mule runtime instead.

I have ran into a blocker with DataWeave and bitwise operators, specifically how to handle negative hex numbers.

Currently, my Kafka/Debezium producer is providing the following value +PB34g== which should decode to -118.458398

With Python I can use Two's Complement to shift and convert to negative. But, I haven't found a comparable DataWeave solution.

We decode the Base64 value with this function, and then convert to integer with the function below.

    # decode the integer
    # and handle negative values
    def _b64_to_int(self, value):
        num = int.from_bytes(base64.b64decode(value), 'big')
        # now check the sign
        # and if negative, take 2's complement
        # TODO: works, but isn't 64-bit safe
        if num & (1 << 31):
            num -= int('1' + '00' * 4, 16)
        #print(f"{value} = {num}")
        return num

I can handle this in a Java class, but would prefer to use DataWeave if possible.

    # and handle negative values
    def _b64_to_int(self, value):
        num = int.from_bytes(base64.b64decode(value), 'big')
        # now check the sign
        # and if negative, take 2's complement
        # TODO: works, but isn't 64-bit safe
        if num & (1 << 31):
            num -= int('1' + '00' * 4, 16)
        #print(f"{value} = {num}")
        return num

I have the following DataWeave to convert from Base64 to a number. I have found this article where custom bitwise functions were created, but they did not handle negative values.

%dw 2.0
output application/json
import * from dw::core::Binaries
fun to_number(b64) = dw::core::Numbers::fromHex(toHex(fromBase64(b64)))
fun to_decimal(num, scale) = to_number(num) as Number / pow(10, scale)
---
to_decimal("+PB34g==", 5)

答案1

得分: 1

I translated the logic from the Python snippet to DataWeave and added the to_decimal() function from your DataWeave script to get the expected result.

WARNING: I haven't validated the logic nor the mathematics of it.

%dw 2.0
output application/json
import * from dw::core::Binaries
import * from dw::core::Numbers

var leftshift_1_31=fromBinary("10000000000000000000000000000000")
var hex_100000000="0100000000"

fun AND(bin1, bin2) = do {
    var b1=getBinary(bin1, 64)
    var b2=getBinary(bin2, 64)
    ---
    fromBinary(b1 map ($ as Number * b2[$$] as Number) reduce ($$++$))
}

fun getBinary(i: Number, size: Number) = do {
    var b = toBinary(i)
    ---
    dw::core::Strings::leftPad(b, size, '0') splitBy ''
}

fun to_number(b64) = do {
    var result = dw::core::Numbers::fromHex(toHex(fromBase64(b64)))
    ---
    if ((AND(result, leftshift_1_31)==0))
        result 
    else
        result - dw::core::Numbers::fromHex(hex_100000000) 
}

fun to_decimal(num, scale) = to_number(num) as Number / pow(10, scale)
---
to_decimal("+PB34g==", 6)

Output:

-118.458398
英文:

I translated the logic from the Python snippet to DataWeave and added the to_decimal() function from your DataWeave script to get the expected result.

WARNING: I haven't validated the logic nor the mathematics of it.

%dw 2.0
output application/json
import * from dw::core::Binaries
import * from dw::core::Numbers

var leftshift_1_31=fromBinary("10000000000000000000000000000000")
var hex_100000000="0100000000"

fun AND(bin1, bin2) = do {
    var b1=getBinary(bin1, 64)
    var b2=getBinary(bin2, 64)
    ---
    fromBinary(b1 map ($ as Number * b2[$$] as Number) reduce ($$++$))
}

fun getBinary(i: Number, size: Number) = do {
    var b = toBinary(i)
    ---
    dw::core::Strings::leftPad(b, size, '0') splitBy ''
}

fun to_number(b64) = do {
    var result = dw::core::Numbers::fromHex(toHex(fromBase64(b64)))
    ---
    if ((AND(result, leftshift_1_31)==0))
        result 
    else
        result - dw::core::Numbers::fromHex(hex_100000000) 
}

fun to_decimal(num, scale) = to_number(num) as Number / pow(10, scale)
---
to_decimal("+PB34g==", 6)

Output:

-118.458398

huangapple
  • 本文由 发表于 2023年4月11日 01:07:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/75979110.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定