16進数から10進数の変換
Posted feedbacks - HSP
文字列処理でごり押し。
速度の最適化はしていません。
理論上は無限桁の整数に対応していますが、メモリ・時間の誓約を加味すると……?
わたしのラップトップでは 150 桁まで確認できました。( *LOmake を使用 )
速度の最適化はしていません。
理論上は無限桁の整数に対応していますが、メモリ・時間の誓約を加味すると……?
わたしのラップトップでは 150 桁まで確認できました。( *LOmake を使用 )
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 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 | // ※負数は扱えない
// ※HSP3.2b2 のみ対応( strf, strtrim )
#module StrCalclator
#define true 1
#define false 0
#define ctype numrg(%1,%2,%3) \
( ((%2) <= (%1)) && ((%1) <= (%3)) )
//------------------------------------------------
// 数字 → 数値
//------------------------------------------------
#defcfunc charToNumber int chr
if ( numrg(chr, '0', '9') ) {
return chr - '0'
} else : if ( numrg(chr, 'a', 'z') ) {
return chr - 'a' + 10
} else : if ( numrg(chr, 'A', 'Z') ) {
return chr - 'A' + 10
}
return 0
//------------------------------------------------
// 数値 → 数字
//------------------------------------------------
#defcfunc numberToChar int n
if ( numrg(n, 0, 9) ) {
return n + '0'
} else : if ( numrg(n, 10, 36) ) {
return n + 'A'
} else {
return ' '
}
//------------------------------------------------
// 桁を大きい方にそろえる
//
// @ 足りない分は左側に0で詰めます
//------------------------------------------------
#deffunc Str_toSamePlaces var p1, var p2, local len, local sResult
len = strlen(p1), strlen(p2)
if ( len(0) == len(1) ) {
} else : if ( len(0) > len(1) ) {
p2 = strf("%0"+ len(0) +"s", p2)
len(1) = len(0)
} else {
p1 = strf("%0"+ len(1) +"s", p1)
len(0) = len(1)
}
return len(0)
//------------------------------------------------
// 文字列同士の加法
//------------------------------------------------
#defcfunc StrCalc_add str p1, str p2, \
local sLeft, local sRight, local sResult, \
local cntRoundUp, local places, local n, local c
sLeft = p1
sRight = p2
cntRoundUp = 0 // 繰り上がり (適当英単語)
// 桁を大きい方にそろえる
Str_toSamePlaces sLeft, sRight
places = stat
sdim sResult, places + 1
// 桁ごとの足し算
for i, places - 1, -1, -1 // 後ろの桁からの減数ループ
// 桁の数値を得る
c(0) = peek(sLeft, i)
c(1) = peek(sRight, i)
n(0) = charToNumber(c(0))
n(1) = charToNumber(c(1))
// 繰り上がりを考慮して足し算する
n(2) = n(0) + n(1) + cntRoundUp
cntRoundUp = 0
// 繰り上がり?
if ( n(2) >= 10 ) {
cntRoundUp ++
n(2) -= 10
}
c(2) = numberToChar(n(2))
// 結果に書き込む
poke sResult, i, c(2)
next
// 最後の繰り上がり
if ( cntRoundUp ) {
sResult = strf("%c", numberToChar(cntRoundUp)) + sResult
}
return sResult
//------------------------------------------------
// 文字列同士の乗法
//------------------------------------------------
#defcfunc StrCalc_mul str p1, str p2, \
local sLeft, local sRight, local sMiddle, local sResult, \
local cntRoundUp, local places, local n, local c
sLeft = p1
sRight = p2
places = strlen(sLeft), strlen(sRight)
sdim sResult, places * 2
sdim sMiddle, places + 1, places // 途中式
// 右辺の桁ごとにループ
repeat places(1)
c(1) = peek(sRight, places(1) - cnt - 1)
n(1) = charToNumber(c(1))
if ( n(1) == 0 ) {
sMiddle(cnt) = "0"
continue
}
cntRoundUp = 0 // 繰り上がり (適当英単語)
// 桁ごとのかけ算
for i, places(0) - 1, -1, -1 // 後ろの桁からの減数ループ
// 桁の数値を得る
c(0) = peek(sLeft, i)
n(0) = charToNumber(c(0))
// 繰り上がりを考慮してかけ算する
n(2) = n(0) * n(1) + cntRoundUp
cntRoundUp = 0
repeat
if ( n(2) >= 10 ) {
cntRoundUp ++
n(2) -= 10
} else {
break
}
loop
c(2) = numberToChar(n(2))
// 途中式に書き込む
poke sMiddle(cnt), i, c(2)
next
// 最後の繰り上がり
if ( cntRoundUp ) {
sMiddle(cnt) = strf("%c%s", numberToChar(cntRoundUp), sMiddle(cnt))
}
// 後ろ側に 0 を並べて桁揃え
sMiddle(cnt) += strf("%0"+ cnt +"s", "")
loop
// 途中式をすべて足し合わせる
repeat places(1)
sResult = StrCalc_add(sResult, sMiddle(cnt))
loop
return sResult
//------------------------------------------------
// 文字列の累乗
//------------------------------------------------
#defcfunc StrCalc_pow str p1, int p2, local sResult
sdim sResult
sResult = "1"
repeat p2
sResult = StrCalc_mul(sResult, p1)
loop
return sResult
//------------------------------------------------
// 10進数以外の基数の文字列を10進数文字列に変換
//
// @ 2 ~ 32 進数まで保証
// @ 負数は扱えない
//------------------------------------------------
#defcfunc StrCalc_toDigit str p1, int fromRadix, \
local sFromRadix, local sInput, local sDigit
if ( fromRadix <= 0 ) { return "" } // エラー
if ( fromRadix == 10 ) { return p1 } // 変換する必要なし
sdim sInput, 320
sdim sDigit, 320
sFromRadix = str(fromRadix)
// 小文字にする
sInput = p1
places = strlen(sInput)
// 十進数に直す
repeat places
c = peek(sInput, places - (cnt + 1))
stmp = StrCalc_mul( str( charToNumber(c) ), StrCalc_pow(sFromRadix, cnt) )
sDigit = StrCalc_add( sDigit, stmp )
loop
return sDigit
#global
*main
sLeft = "12437308CCB6", "2C9C1227FC6520B", "ff"
sResult = "20080902065334", "200904012311450123", "255"
repeat 3
mes "#"+ cnt +"\n解答:"+ StrCalc_toDigit(sLeft(cnt), 16) +"\n正答:"+ sResult(cnt)
mes
loop
stop
// おまけ
*LOmake
n = 15 // 入力する16進数の桁数の10分の1
sdim sHex, 1024
repeat n
sHex += "1234567890"
loop
sDig = StrCalc_toDigit(sHex, 16)
logmes sDig
stop
|


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