16進数から10進数の変換
Posted feedbacks - XSLT
XSLT1.0で実装。
XPath1.0の数値型は浮動小数点数しか存在せず、その精度は処理系によって異なるようです。倍精度くらいで実装されているようで、この数値型をそのまま利用すると(29-51行)、条件2の変換が正確に行えませんでした。
そこで、入力された16進数を上位ビットと下位ビットに分けて数値化し、10進数として表示する時に2つの数を合成する手法を用いました(52-95行)。それでもFirefoxだと16桁でヘタってしまいましたが、Xalanは26桁まで頑張ってくれました。
実行結果(実行方法:適当なXMLにこのXSLTを適用)
- Firefox 3.5.1:
0x12437308CCB6 = 20080902065334.
0x2C9C1227FC6520B = 200904012311450100.
0x12437308CCB6 = (bignum) 20080902065334.
0x2C9C1227FC6520B = (bignum) 200904012311450123.
0xCDEF89AB45670123 = (bignum) 14839230665905865403.
0x112233445566778899AABBCCDD = (bignum) 1357463230989497420518412782813.
- Xalan 1.10.0:
0x12437308CCB6 = 20080902065334.
0x2C9C1227FC6520B = 200904012311450112.
0x12437308CCB6 = (bignum) 20080902065334.
0x2C9C1227FC6520B = (bignum) 200904012311450123.
0xCDEF89AB45670123 = (bignum) 14839230665905864995.
0x112233445566778899AABBCCDD = (bignum) 1357463230989497419223659171037.
XPath1.0の数値型は浮動小数点数しか存在せず、その精度は処理系によって異なるようです。倍精度くらいで実装されているようで、この数値型をそのまま利用すると(29-51行)、条件2の変換が正確に行えませんでした。
そこで、入力された16進数を上位ビットと下位ビットに分けて数値化し、10進数として表示する時に2つの数を合成する手法を用いました(52-95行)。それでもFirefoxだと16桁でヘタってしまいましたが、Xalanは26桁まで頑張ってくれました。
実行結果(実行方法:適当なXMLにこのXSLTを適用)
- Firefox 3.5.1:
0x12437308CCB6 = 20080902065334.
0x2C9C1227FC6520B = 200904012311450100.
0x12437308CCB6 = (bignum) 20080902065334.
0x2C9C1227FC6520B = (bignum) 200904012311450123.
0xCDEF89AB45670123 = (bignum) 14839230665905865403.
0x112233445566778899AABBCCDD = (bignum) 1357463230989497420518412782813.
- Xalan 1.10.0:
0x12437308CCB6 = 20080902065334.
0x2C9C1227FC6520B = 200904012311450112.
0x12437308CCB6 = (bignum) 20080902065334.
0x2C9C1227FC6520B = (bignum) 200904012311450123.
0xCDEF89AB45670123 = (bignum) 14839230665905864995.
0x112233445566778899AABBCCDD = (bignum) 1357463230989497419223659171037.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | <?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="text" />
<xsl:variable name="var" select="document('')/xsl:stylesheet/xsl:template[@name='var']" />
<xsl:template match="/">
<xsl:variable name="test1" select="'0x12437308CCB6'" />
<xsl:variable name="test2" select="'0x2C9C1227FC6520B'" />
<xsl:variable name="test3" select="'0xCDEF89AB45670123'" />
<xsl:variable name="test4" select="'0x112233445566778899AABBCCDD'" />
<xsl:call-template name="hex2dec">
<xsl:with-param name="input" select="$test1" />
</xsl:call-template>
<xsl:call-template name="hex2dec">
<xsl:with-param name="input" select="$test2" />
</xsl:call-template>
<xsl:call-template name="bighex2dec">
<xsl:with-param name="input" select="$test1" />
</xsl:call-template>
<xsl:call-template name="bighex2dec">
<xsl:with-param name="input" select="$test2" />
</xsl:call-template>
<xsl:call-template name="bighex2dec">
<xsl:with-param name="input" select="$test3" />
</xsl:call-template>
<xsl:call-template name="bighex2dec">
<xsl:with-param name="input" select="$test4" />
</xsl:call-template>
</xsl:template>
<xsl:template name="hex2dec">
<xsl:param name="input" />
<xsl:value-of select="$input" /> = <!--
--><xsl:apply-templates select="$var" mode="translate">
<xsl:with-param name="input" select="substring($input,3)" />
</xsl:apply-templates>.
<!--
--></xsl:template>
<xsl:template match="xsl:template" mode="translate">
<xsl:param name="input" />
<xsl:param name="output" select="0" />
<xsl:choose>
<xsl:when test="$input=''">
<xsl:value-of select="$output" />
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="." mode="translate">
<xsl:with-param name="input" select="substring($input,2)" />
<xsl:with-param name="output" select="$output * 16 + hex[@name=substring($input,1,1)]" />
</xsl:apply-templates>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="bighex2dec">
<xsl:param name="input" />
<xsl:variable name="partition" select="floor((string-length($input)-2) div 2)" />
<xsl:value-of select="$input" /> = (bignum) <!--
--><xsl:apply-templates select="$var" mode="btranslate">
<xsl:with-param name="input" select="substring($input,3,$partition)" />
<xsl:with-param name="input2" select="substring($input,3+$partition)" />
</xsl:apply-templates>.
<!--
--></xsl:template>
<xsl:template match="xsl:template" mode="btranslate">
<xsl:param name="input" select="''" />
<xsl:param name="input2" select="''" />
<xsl:param name="output" select="0" />
<xsl:param name="output2" select="0" />
<xsl:variable name="in1" select="substring($input,1,1)" />
<xsl:choose>
<xsl:when test="$input=''">
<xsl:choose>
<xsl:when test="$input2=''">
<xsl:variable name="outA" select="substring($output,1,string-length($output)-string-length($output2))" />
<xsl:variable name="outB" select="substring($output,string-length($output)-string-length($output2)+1) + $output2" />
<xsl:variable name="overflow" select="number(string-length($outB)>string-length($output2))" />
<xsl:value-of select="$outA + $overflow" />
<xsl:value-of select="substring($outB,1+$overflow)" />
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="." mode="btranslate">
<xsl:with-param name="input2" select="substring($input2,2)" />
<xsl:with-param name="output" select="$output*16" />
<xsl:with-param name="output2" select="$output2 * 16 + hex[@name=substring($input2,1,1)]" />
</xsl:apply-templates>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="." mode="btranslate">
<xsl:with-param name="input" select="substring($input,2)" />
<xsl:with-param name="input2" select="$input2" />
<xsl:with-param name="output" select="$output * 16 + hex[@name=substring($input,1,1)]" />
</xsl:apply-templates>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="text()" mode="translate" />
<xsl:template match="text()" mode="btranslate" />
<xsl:template match="text()" />
<xsl:template name="var">
<hex name="0">0</hex>
<hex name="1">1</hex>
<hex name="2">2</hex>
<hex name="3">3</hex>
<hex name="4">4</hex>
<hex name="5">5</hex>
<hex name="6">6</hex>
<hex name="7">7</hex>
<hex name="8">8</hex>
<hex name="9">9</hex>
<hex name="A">10</hex>
<hex name="B">11</hex>
<hex name="C">12</hex>
<hex name="D">13</hex>
<hex name="E">14</hex>
<hex name="F">15</hex>
</xsl:template>
</xsl:stylesheet>
|

shojiHIDAKA #8955() Rating1/1=1.00
16進数を10進数に変換してください。
ただし、入出力は文字列とし、次の変換は最低必ずできなければいけないこととします。
2.0x2C9C1227FC6520B →200904012311450123
あわせて、扱える最大の整数も明らかにしてください。
[ reply ]