【问题标题】:How to convert an 8-bit integer into a binary string in xquery?如何在 xquery 中将 8 位整数转换为二进制字符串?
【发布时间】:2011-02-10 12:57:18
【问题描述】:

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

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

【问题讨论】:

    标签: binary integer xquery


    【解决方案1】:

    作为一个小提示,如果您返回的是文本,而不是 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])
    };
    

    【讨论】:

    • 我们确实考虑过这一点,但没有尝试。我怀疑也非常简单和快速(这对我们来说可能很重要)。我们的应用程序的输出将是 XML 或文本。在这种情况下,它可能是 XML。
    • xs:byte 应该是 xs:unsignedByte 吗?
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      如果较慢,递归函数就很清楚了:

      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
      

      };

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

      【讨论】:

      • 我喜欢递归。我必须将 floor() 函数包装在 xs:integer() 中才能让 saxonb(?) xquery 运行它。我还必须将数字更改为 xs:integer。如果您只想要数字的最小长度二进制表示,这会很好。
      • 我在 eXist 沙箱 demo.exist-db.org/exist/sandbox/sandbox.xql 中测试了代码 - 撒克逊必须更严格 - 只能说 xs:integer($d div 2)。要获得固定长度的字符串,请使用 string-pad: declare function local:decimal-to-binary($d as xs:integer,$length as xs:integer){ let $binary := local:decimal-to-binary( $d) return concat (string-pad("0", $length - string-length($binary)),$binary) };本地:十进制到二进制(42,8)
      • 上面的函数是有效的 XQuery - 函数参数转换规则应该意味着参数被强制转换为 xs:integers(因为这是参数所期望的)。我很惊讶撒克逊人不喜欢它。
      • @Oliver:我正在使用来自 Saxonica 的 Saxon 9.1.0.6J。错误是 XPTY0004: local:decimal-to-binary() 第一个参数的必需项类型是 xs:integer;提供的值具有项目类型 xs:decimal at local:decimal-to-binary() (file:dec-bin.xq#46) at local:decimal-to-binary() (file:dec-bin.xq#58)
      猜你喜欢
      • 2012-02-27
      • 1970-01-01
      • 1970-01-01
      • 2017-06-14
      • 2018-12-11
      • 2018-09-15
      • 2018-03-01
      • 1970-01-01
      相关资源
      最近更新 更多