在 Solidity 中将 uint24 转换为 HEX 字符串
Convert uint24 to HEX string in Solidity
我正在尝试将一种 0x00ff08
的 uint24 值转换为人类可读的 string
,在我将部署在 RSK 上的 Solidity 智能合约中具有相同的字符。在我关于 的问题中,有人建议我出于这些目的使用函数
function uint24tohexstr(uint24 i) public pure returns (string memory) {
bytes memory o = new bytes(6);
uint24 mask = 0x00000f;
o[5] = bytes1(uint8tohexchar(uint8(i & mask)));
i = i >> 4;
o[4] = bytes1(uint8tohexchar(uint8(i & mask)));
i = i >> 4;
o[3] = bytes1(uint8tohexchar(uint8(i & mask)));
i = i >> 4;
o[2] = bytes1(uint8tohexchar(uint8(i & mask)));
i = i >> 4;
o[1] = bytes1(uint8tohexchar(uint8(i & mask)));
i = i >> 4;
o[0] = bytes1(uint8tohexchar(uint8(i & mask)));
return string(o);
}
我想在那个函数中使用一个循环并像这样重写它
function uint24ToHexStr(uint24 i) public pure returns (string memory) {
bytes memory o = new bytes(6);
uint24 mask = 0x00000f; // hex 15
for(uint k = 5; k >= 0; k -= 1) {
o[k] = bytes1(uint8ToHexCharCode(uint8(i & mask)));
i >>= 4;
}
return string(o);
}
但不幸的是,此函数会导致运行时错误,因为在最后一次迭代中,无符号整数 k
变为 -1
。我首先想到的是将 k 增加 1,这样
for(uint k = 6; k >= 1; k -= 1) {
o[k - 1] = bytes1(uint8ToHexCharCode(uint8(i & mask)));
}
谁能想出更优雅的方法来实现相同的结果?
这一行:
for(uint k = 5; k >= 0; k -= 1) {
如果 k
是 uint
类型,k >= 0
什么时候会计算为 false? (提示:从不)
将 k
从类型 uint
更改为 int
,问题就解决了。
for(int k = 5; k >= 0; k -= 1) {
o[k] = bytes1(uint8ToHexCharCode(uint8(i & mask)));
i >>= 4;
}
或者
for(uint k = 0; k< 6; k += 1) {
o[5-k] = bytes1(uint8ToHexCharCode(uint8(i & mask)));
i >>= 4;
}
我喜欢中的第二个选项;并想如果我们使用不同类型的循环控制结构会怎样。常规 while
循环会继承 for
循环所具有的相同“最终迭代 uint
下溢”问题。另一方面,切换到 do .. while
循环允许您将条件的评估从 在 迭代之前检查,转移到在 之后检查 迭代。这可以像这样应用于您的实现:
function uint24ToHexStr(uint24 i) public pure returns (string memory) {
bytes memory o = new bytes(6);
uint24 mask = 0x00000f; // hex 15
uint k = 6;
do {
k--;
o[k] = bytes1(uint8ToHexCharCode(uint8(i & mask)));
i >>= 4;
} while (k > 0);
return string(o);
}
这既避免了 uint
下溢,也不需要 k - 1
用于循环内的数组索引。就 gas 成本而言,我会“猜测”它会接近上一个问题中相同功能的原始实现。 (但实际上都尝试并比较以确认)
替代答案,也从前向迭代中得到一些启发,但不是颠倒索引顺序,
通过按位与掩码 switching 获得目标半字节
到 5 个半字节(20 位)的位移。
像这样:
function uint24ToHexStrAlt2(uint24 i) public pure returns (string memory) {
bytes memory o = new bytes(6);
uint k = 0;
do {
o[k] = bytes1(uint8ToHexCharCode(uint8(i >> 20))); // shift by 5 nibbles instead of mask
i <<= 4;
k +=1;
} while (k < 6);
return string(o);
}
我正在尝试将一种 0x00ff08
的 uint24 值转换为人类可读的 string
,在我将部署在 RSK 上的 Solidity 智能合约中具有相同的字符。在我关于
function uint24tohexstr(uint24 i) public pure returns (string memory) {
bytes memory o = new bytes(6);
uint24 mask = 0x00000f;
o[5] = bytes1(uint8tohexchar(uint8(i & mask)));
i = i >> 4;
o[4] = bytes1(uint8tohexchar(uint8(i & mask)));
i = i >> 4;
o[3] = bytes1(uint8tohexchar(uint8(i & mask)));
i = i >> 4;
o[2] = bytes1(uint8tohexchar(uint8(i & mask)));
i = i >> 4;
o[1] = bytes1(uint8tohexchar(uint8(i & mask)));
i = i >> 4;
o[0] = bytes1(uint8tohexchar(uint8(i & mask)));
return string(o);
}
我想在那个函数中使用一个循环并像这样重写它
function uint24ToHexStr(uint24 i) public pure returns (string memory) {
bytes memory o = new bytes(6);
uint24 mask = 0x00000f; // hex 15
for(uint k = 5; k >= 0; k -= 1) {
o[k] = bytes1(uint8ToHexCharCode(uint8(i & mask)));
i >>= 4;
}
return string(o);
}
但不幸的是,此函数会导致运行时错误,因为在最后一次迭代中,无符号整数 k
变为 -1
。我首先想到的是将 k 增加 1,这样
for(uint k = 6; k >= 1; k -= 1) {
o[k - 1] = bytes1(uint8ToHexCharCode(uint8(i & mask)));
}
谁能想出更优雅的方法来实现相同的结果?
这一行:
for(uint k = 5; k >= 0; k -= 1) {
如果 k
是 uint
类型,k >= 0
什么时候会计算为 false? (提示:从不)
将 k
从类型 uint
更改为 int
,问题就解决了。
for(int k = 5; k >= 0; k -= 1) {
o[k] = bytes1(uint8ToHexCharCode(uint8(i & mask)));
i >>= 4;
}
或者
for(uint k = 0; k< 6; k += 1) {
o[5-k] = bytes1(uint8ToHexCharCode(uint8(i & mask)));
i >>= 4;
}
我喜欢while
循环会继承 for
循环所具有的相同“最终迭代 uint
下溢”问题。另一方面,切换到 do .. while
循环允许您将条件的评估从 在 迭代之前检查,转移到在 之后检查 迭代。这可以像这样应用于您的实现:
function uint24ToHexStr(uint24 i) public pure returns (string memory) {
bytes memory o = new bytes(6);
uint24 mask = 0x00000f; // hex 15
uint k = 6;
do {
k--;
o[k] = bytes1(uint8ToHexCharCode(uint8(i & mask)));
i >>= 4;
} while (k > 0);
return string(o);
}
这既避免了 uint
下溢,也不需要 k - 1
用于循环内的数组索引。就 gas 成本而言,我会“猜测”它会接近上一个问题中相同功能的原始实现。 (但实际上都尝试并比较以确认)
替代答案,也从前向迭代中得到一些启发
function uint24ToHexStrAlt2(uint24 i) public pure returns (string memory) {
bytes memory o = new bytes(6);
uint k = 0;
do {
o[k] = bytes1(uint8ToHexCharCode(uint8(i >> 20))); // shift by 5 nibbles instead of mask
i <<= 4;
k +=1;
} while (k < 6);
return string(o);
}