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

时间:2010-04-21 10:19:51

标签: binary integer xquery

在今天的工作中,我们将这一尝试汇总在一起:

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)
    )
};

3 个答案:

答案 0 :(得分:2)

作为次要注意事项,如果您要返回文字而不是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])
};

答案 1 :(得分:1)

如果速度较慢,则递归函数清晰:

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)

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

};

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

答案 2 :(得分:1)

我能想到的最有效的反向方式(至少在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微秒,因此无需担心。