如何在xquery中将8位整数转换为二进制字符串?

发布于 2024-08-29 20:22:28 字数 836 浏览 7 评论 0原文

今天工作中,我们拼凑了这样的尝试:

xquery version "1.0";
declare option saxon:output             "omit-xml-declaration=yes";
declare variable $x := 99;

string-join(
    for $b in (128,64,32,16,8,4,2,1)
    let $xm := $x mod ($b*2)
    return
        if ( $xm >= $b ) then "1" else "0"
, "")

你有更好的办法吗?

根据奥利弗的回答,我做了相反的功能。

declare function local:bin-byte($x as xs:string) as xs:unsignedByte
{
  let $binary-nibbles := ("0000", "0001", "0010", "0011", 
                          "0100", "0101", "0110", "0111",
                          "1000", "1001", "1010", "1011",
                          "1100", "1101", "1110", "1111")
  return xs:unsignedByte(
    (index-of( $binary-nibbles, substring($x,1,4) )-1) * 16
    + (index-of( $binary-nibbles, substring($x,5,4) )-1)
    )
};

At work today, we threw together this attempt:

xquery version "1.0";
declare option saxon:output             "omit-xml-declaration=yes";
declare variable $x := 99;

string-join(
    for $b in (128,64,32,16,8,4,2,1)
    let $xm := $x mod ($b*2)
    return
        if ( $xm >= $b ) then "1" else "0"
, "")

Do you have a better way?

Taking Oliver's answer, I have made the reverse function.

declare function local:bin-byte($x as xs:string) as xs:unsignedByte
{
  let $binary-nibbles := ("0000", "0001", "0010", "0011", 
                          "0100", "0101", "0110", "0111",
                          "1000", "1001", "1010", "1011",
                          "1100", "1101", "1110", "1111")
  return xs:unsignedByte(
    (index-of( $binary-nibbles, substring($x,1,4) )-1) * 16
    + (index-of( $binary-nibbles, substring($x,5,4) )-1)
    )
};

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

故人如初 2024-09-05 20:22:28

需要注意的是,如果您返回文本,而不是 XML,那么您最好设置 method=text 而不是 omit-xml-declaration=yes,尽管在​​此情况没有什么区别。

另一种解决方案是使用查找表:

declare function local:binary($x as xs:unsignedByte) as xs:string
{
  let $binary-nibbles := ("0000", "0001", "0010", "0011", 
                          "0100", "0101", "0110", "0111",
                          "1000", "1001", "1010", "1011",
                          "1100", "1101", "1110", "1111")
  return concat($binary-nibbles[$x idiv 16 + 1],
                $binary-nibbles[$x mod 16 + 1])
};

As a minor note, if you are returning text, not XML then you are probably better off setting method=text rather than omit-xml-declaration=yes, although in this case it makes no difference.

An alternative solution is using a lookup table:

declare function local:binary($x as xs:unsignedByte) as xs:string
{
  let $binary-nibbles := ("0000", "0001", "0010", "0011", 
                          "0100", "0101", "0110", "0111",
                          "1000", "1001", "1010", "1011",
                          "1100", "1101", "1110", "1111")
  return concat($binary-nibbles[$x idiv 16 + 1],
                $binary-nibbles[$x mod 16 + 1])
};
白芷 2024-09-05 20:22:28

我能想到的最有效的反向操作方法(至少在 XQSharp 中)是:

declare function local:binary-string-to-integer($binary as xs:string)
                   as xs:integer
{
  local:binary-codepoints-to-integer(string-to-codepoints($binary), 1, 0)
};

declare function local:binary-codepoints-to-integer(
                   $codepoints as xs:integer*,
                   $current-index as xs:integer,
                   $result as xs:integer)
                   as xs:integer
{
  let $current-codepoint := $codepoints[$current-index]
  return
    if (empty($current-codepoint))
    then $result
    else local:binary-codepoints-to-integer(
           $codepoints,
           $current-index + 1,
           2 * $result + $current-codepoint - string-to-codepoints("0"))
};

快速性能测试显示两种方法在解释查询时执行的效果大致相同,但在编译查询时此方法大约快 50% 。递归函数方法还具有不限于无符号字节的好处。

无论哪种方式,运行时间约为 10 微秒,因此无需担心。

The most efficient way I can think of doing the reverse (at least in XQSharp) is:

declare function local:binary-string-to-integer($binary as xs:string)
                   as xs:integer
{
  local:binary-codepoints-to-integer(string-to-codepoints($binary), 1, 0)
};

declare function local:binary-codepoints-to-integer(
                   $codepoints as xs:integer*,
                   $current-index as xs:integer,
                   $result as xs:integer)
                   as xs:integer
{
  let $current-codepoint := $codepoints[$current-index]
  return
    if (empty($current-codepoint))
    then $result
    else local:binary-codepoints-to-integer(
           $codepoints,
           $current-index + 1,
           2 * $result + $current-codepoint - string-to-codepoints("0"))
};

A quick performance test shows both methods to perform about the same when the query is interpreted, but this method is about 50% faster when the query is compiled. The recursive function method also has the benefit of not being limited to unsigned bytes.

Either way the runtime is about 10 microseconds so is nothing to be concerned about.

郁金香雨 2024-09-05 20:22:28

递归函数如果较慢则很清晰:

declare function local:decimal-to-binary ($d as xs:integer) as xs:string {
 if ($d > 0)
 then concat(local:decimal-to-binary(floor($d div 2)),$d mod 2)
 else ""
};

例如

local:decimal-to-binary(42)

使用逆:

declare function local:binary-to-decimal($b as xs:string) as xs:integer {
 if ($b ne "")
 then local:binary-to-decimal(substring($b, 1, string-length($b)- 1)) * 2 
       + number(substring ($b, string-length($b),1))
 else 0

};

本地:二进制到十进制(本地:十进制到二进制(42))

Recursive functions are clear if slower:

declare function local:decimal-to-binary ($d as xs:integer) as xs:string {
 if ($d > 0)
 then concat(local:decimal-to-binary(floor($d div 2)),$d mod 2)
 else ""
};

eg

local:decimal-to-binary(42)

with inverse:

declare function local:binary-to-decimal($b as xs:string) as xs:integer {
 if ($b ne "")
 then local:binary-to-decimal(substring($b, 1, string-length($b)- 1)) * 2 
       + number(substring ($b, string-length($b),1))
 else 0

};

local:binary-to-decimal(local:decimal-to-binary(42))

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文