Iは、ASCII形式にバイナリ形式で表現された整数の任意の長さを変換したいと思います。
整数ためである一例として33023
、16進数のバイトがあります0x80ff
。私が表現したい0x80ff
のASCIIフォーマットに33023
16進表現を有します0x3333303233
。
私は、に取り組んでいますJavaのカードの私は、バイナリ操作によって手動で変換を行う必要がありますので、文字列型を認識しない環境。
どのような16ビットスマートカード上のJavaカード環境としてこれを解決するについて行くための最も効率的な方法であることは非常に制約です。
これは、ベースの変換を必要とし、ベース変換は、大きな整数演算を使用して、全体数の上で実行されたとして、あなたが考えることよりも難しいです。
もちろん、それは我々が、具体的な目的のために言った大きな整数演算の効率的な実装を作成することができないという意味ではありません。ここでの実装は、左ゼロの(通常のJavaカードに必要とされる)と、パッドと追加のメモリ(!)を使用していないということです。入力値が上書きされます - あなたはかかわらず、それを維持したい場合は、ビッグエンディアン数の元の値をコピーする必要があります。RAMにそれを置くことを強くお勧めします。
このコードは、単に剰余を返し、新しいベース(小数点以下10)でバイトを分割します。残りは次ある最下位桁。入力値は、現在分割されているように、次の残りの部分は、以前のものよりわずか一つの位置より重要である数字です。これは値がゼロであり、計算が完了するまで残りを分割し、戻り続けます。
アルゴリズムのトリッキーな部分は、バイトにわたって尾分割を使用して残りを戻しながら、代わりに10で値を除算内部ループです。これは、実行ごとに残り/小数点以下の数字を提供します。関数のオーダーであることが、この手段はまた、O(N)ここで、nは結果(単一の操作として尾分割を定義する)の桁数です。そのノートNを算出することができるceil(bigNumBytes * log_10(256))
また、予め計算で存在するの結果:BCD_SIZE_PER_BYTES
表。log_10(256)
もちろん、一定の小数点値、どこかで上向きの2.408
。
ここでの最適化(異なるバージョンの編集を参照)との最終的なコードは次のようになります。
/**
* Converts an unsigned big endian value within the buffer to the same value
* stored using ASCII digits. The ASCII digits may be zero padded, depending
* on the value within the buffer.
* <p>
* <strong>Warning:</strong> this method zeros the value in the buffer that
* contains the original number. It is strongly recommended that the input
* value is in fast transient memory as it will be overwritten multiple
* times - until it is all zero.
* </p>
* <p>
* <strong>Warning:</strong> this method fails if not enough bytes are
* available in the output BCD buffer while destroying the input buffer.
* </p>
* <p>
* <strong>Warning:</strong> the big endian number can only occupy 16 bytes
* or less for this implementation.
* </p>
*
* @param uBigBuf
* the buffer containing the unsigned big endian number
* @param uBigOff
* the offset of the unsigned big endian number in the buffer
* @param uBigLen
* the length of the unsigned big endian number in the buffer
* @param decBuf
* the buffer that is to receive the BCD encoded number
* @param decOff
* the offset in the buffer to receive the BCD encoded number
* @return decLen, the length in the buffer of the received BCD encoded
* number
*/
public static short toDecimalASCII(byte[] uBigBuf, short uBigOff,
short uBigLen, byte[] decBuf, short decOff) {
// variables required to perform long division by 10 over bytes
// possible optimization: reuse remainder for dividend (yuk!)
short dividend, division, remainder;
// calculate stuff outside of loop
final short uBigEnd = (short) (uBigOff + uBigLen);
final short decDigits = BYTES_TO_DECIMAL_SIZE[uBigLen];
// --- basically perform division by 10 in a loop, storing the remainder
// traverse from right (least significant) to the left for the decimals
for (short decIndex = (short) (decOff + decDigits - 1); decIndex >= decOff; decIndex--) {
// --- the following code performs tail division by 10 over bytes
// clear remainder at the start of the division
remainder = 0;
// traverse from left (most significant) to the right for the input
for (short uBigIndex = uBigOff; uBigIndex < uBigEnd; uBigIndex++) {
// get rest of previous result times 256 (bytes are base 256)
// ... and add next positive byte value
// optimization: doing shift by 8 positions instead of mul.
dividend = (short) ((remainder << 8) + (uBigBuf[uBigIndex] & 0xFF));
// do the division
division = (short) (dividend / 10);
// optimization: perform the modular calculation using
// ... subtraction and multiplication
// ... instead of calculating the remainder directly
remainder = (short) (dividend - division * 10);
// store the result in place for the next iteration
uBigBuf[uBigIndex] = (byte) division;
}
// the remainder is what we were after
// add '0' value to create ASCII digits
decBuf[decIndex] = (byte) (remainder + '0');
}
return decDigits;
}
/*
* pre-calculated array storing the number of decimal digits for big endian
* encoded number with len bytes: ceil(len * log_10(256))
*/
private static final byte[] BYTES_TO_DECIMAL_SIZE = { 0, 3, 5, 8, 10, 13,
15, 17, 20, 22, 25, 27, 29, 32, 34, 37, 39 };
入力サイズを拡張するために単にテーブル内の次の小数サイズを計算し、格納...