如果我有两个打包的BCD格式的数字并想添加它们,是不是像这样添加它们的好方法:将两个数字转换为整数,执行正常的整数加法,然后转换结果返回到BCD?使用整数的二进制编码的十进制加法
1
A
回答
1
下面的C99代码将打包的BCD操作数与存储在uint32_t
中的八个BCD数字相加。通过选择uint64_t
来处理16位BCD数字,此代码很容易扩展到更宽的BCD操作数。由于这种方法依赖于位并行处理,因此对于窄分组BCD操作数可能效率不高。
在打包的BCD格式中,每个BCD数字占用一个无符号整数操作数的一个半字节(4位组)。如果以半字节为单位的加法结果大于9,我们希望进入下一个更高的半字节。如果我们使用常规整数加法来添加两个打包的BCD操作数,当半字节总和大于9时,所需的半字节进位不会发生,但是< 16.为了解决这个问题,我们可以为每个半字节和加上一个额外的6。
我们可以发现这个半字节携带如下:两个整数x
,y
的按位总和为x^y
。在常规整数相加期间,在下一个较低位位置有进位的任何位位置,x^y
和x + y
中的位将有所不同。所以我们可以找到带进位的位作为(x^y)^(x + y)
。我们对位4,8,...,32的第3,7,...,31位是有意义的。
如果存在一个小问题因为uint32_t
操作数仅保存32位,所以从位31到位32执行。如果我们发现两个无符号整数的和小于任何一个加数,我们可以检测到这一点。操作7位操作数而不是8位操作数时,可以省略处理从位31执行的三个操作。
/* Add two packed BCD operands, where each uint32_t holds 8 BCD digits */
uint32_t bcd_add (uint32_t x, uint32_t y)
{
uint32_t t0, t1;
t0 = x + 0x66666666; // force nibble carry when BCD digit > 9
t1 = x^y; // bit-wise sum
t0 = t0 + y; // addition with nibble carry
t1 = t1^t0; // (x^y)^(x + y)
t0 = t0 < y; // capture carry-out from bit 31
t1 = (t1 >> 1) | (t0 << 31); // nibble carry-outs in bits 3, 7, ..., 31
t0 = t1 & 0x88888888; // extract nibble carry-outs
t1 = t0 >> 2; // 8 - (8 >> 2) = 6
return x + y + (t0 - t1); // add 6 to any digit with nibble carry-out
}
Knuth的,TAOCP Vol.4A第1部分,提供在应答一个优越的解决方案(需要更少的操作),以从部分7.1.3行使100。该变体特别适合处理器体系结构,其指令可评估三个参数的任何逻辑函数,例如现代NVIDIA GPU的LOP3
指令。
uint32_t median (uint32_t x, uint32_t y, uint32_t z)
{
return (x & (y | z)) | (y & z);
}
uint32_t bcd_add_knuth (uint32_t x, uint32_t y)
{
uint32_t z, u, t;
z = y + 0x66666666;
u = x + z;
t = median (~x, ~z, u) & 0x88888888;
return u - t + (t >> 2);
}
相关问题
- 1. 十进制数的二进制补码
- 2. 将二进制编码的十进制(BCD)解码为无符号整数
- 3. 有符号整数到二进制补码十六进制
- 4. 十进制到二进制(二进制)
- 5. 将带符号的十进制转换为使用二进制补码编码的十六进制
- 6. C中的BCD(二进制编码的十进制)
- 7. 十进制到二进制代码
- 8. 将整数转换为二进制/十进制的MIPS函数?
- 9. 十进制/整数乘法
- 10. 如何将数字(十进制)转换为二进制(二进制)数字和从二进制到十进制?
- 11. 二进制到十进制
- 12. 十进制到二进制Java方法
- 13. 十六进制,八进制,二进制到十进制(C++)
- 14. 二进制,八进制,十六进制到十进制程序
- 15. 使用波纹管算法将二进制整数转换为十进制
- 16. C++中整数的十进制,八进制和十六进制表示法
- 17. 获得负数的二进制补码的十六进制
- 18. C#编码:十六进制到十进制&字符编码
- 19. 对可变位二进制块中的十进制值进行编码/解码
- 20. 二进制十进制负数位集
- 21. 十进制和二进制数处理
- 22. 十进制素数到二进制
- 23. 二进制数据的十六进制编码的目的是什么?
- 24. Python中,如何解码二进制编码的十进制(BCD)的二进制字段的
- 25. Python中十六进制数的二进制补码
- 26. 二进制到十进制和十进制到二进制转换器
- 27. 如何使用C将二进制整数作为十六进制写入二进制文件中使用C
- 28. 从十六进制到十进制,二进制到十进制和八进制到十进制程序C++
- 29. 二进制到十进制的公式
- 30. 将十进制数转换为二进制/十六进制/八进制符号
不知道为什么有接近的投票,这个问题对我来说似乎很好。有许多方法可以使用比特操作等来逐字添加多位BCD操作数。通常,这种方法往往比使用双转换路由更快。您的操作数组成了多少个BCD数字。我可能有一些C代码来演示无转换方法。 – njuffa
当然。有很多可能性(因此选票很近),但是如果您确信可以使其发挥作用,那么为什么不呢? – usr2564301
@njuffa这是打包BCD,2位数字(这是包装在一个8位'uint8_t'。我的一般问题是,当我不做双重转换,我如何检查我的第一个或第二个数字是超过九,如果我想添加两个数字,并且在添加之后他们超过了99,或者第一个数字超过了9,或者第二个数字超过了9,我怎么检查它?我知道我的问题很混乱, t知道如何描述它 – bingo157