Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 如何舍入到整数而不在程序集中分支?_Assembly - Fatal编程技术网

Assembly 如何舍入到整数而不在程序集中分支?

Assembly 如何舍入到整数而不在程序集中分支?,assembly,Assembly,如何在汇编中将整数舍入为最接近的整数?此处不允许使用分支 例如,195*.85=165.75。通常,我将195乘以一个比例因子(100),然后乘以,再除以比例因子。这会给我165分。我怎么才能拿到166 我很抱歉,如果这是一个可怕的问题-我是新的组装!谢谢。整数没有小数位数,因此它已经是一个整数。假设只给了您整数,并告诉您需要使用比例因子将其中一个整数视为小数。。。然后,您可以使用两倍于您需要的比例因子来实现这一点。所以用200代替100。这将导致结果的最后一位为1或0,具体取决于您是否要取整

如何在汇编中将整数舍入为最接近的整数?此处不允许使用分支

例如,195*.85=165.75。通常,我将195乘以一个比例因子(100),然后乘以,再除以比例因子。这会给我165分。我怎么才能拿到166


我很抱歉,如果这是一个可怕的问题-我是新的组装!谢谢。

整数没有小数位数,因此它已经是一个整数。

假设只给了您整数,并告诉您需要使用比例因子将其中一个整数视为小数。。。然后,您可以使用两倍于您需要的比例因子来实现这一点。所以用200代替100。这将导致结果的最后一位为1或0,具体取决于您是否要取整

所以在c风格中,它看起来是这样的

result = (195 * 85) / (100 / 2);
add = result & 1;
result = result / 2 + add;
如果您不应该向上取整(即向下取整),则“添加位”将为0。否则,如果您要进行四舍五入,则“添加位”将为1

我认为这应该为您提供所需的伪代码,以便将其正确地转换为程序集

例如,195*.85=165.75。通常,我将195乘以一个比例因子(100),然后乘以,再除以比例 因素这会给我165分。我怎么才能拿到166

经典的方法是使用两个比例因子的幂和移位,而不是乘和除;我想现在除法和乘法的成本与许多体系结构上的转换相同,您可能更关心保持一定的精度

不管怎样,正如halex所建议的那样,在除法之前要加0.5。最终的效果是,如果小数部分已经是0.5或更大,那么将进位到整数部分。如果没有,那就没有携带

因此:

195*100=19500
19500*0.85=16575
16575+50(即0.5)=16625

16625/100=166在x86汇编中,有FRNDINT指令。

对于正数和负数,asm中有6个字符串

双圆(双x){
收益率(长)(x+0.5+(*(长*)&x>>63));
}

blackbear-如果不先测试小数点是否向上舍入或向下舍入,你就不知道要加1。@finaljon你想做什么类型的舍入-小学生舍入?45.4=45,45.5=46?乘以比例因子100.0,然后在数字为正时加上0.5(否则加上-0.5),再乘以0.85,再除以100.0。@halex您使用when意味着一个不允许的分支。@corsiKa您是对的,忽略了它。也许OP有一个限制,他只想合并正整数:)这是问题的一部分。。。我真的是这样的,这不是我的错,他的问题措辞很糟糕。我偏爱我的方法,因为它很聪明(这并不总是一件好事!!),但实际上我更喜欢它,因为它优雅且直观得多。我唯一要说的缺陷是它的空间比我的答案小:-)使用这种方法比使用我的方法更快溢出50个元素。但由于其概念简单,这是一个相当不错的折衷方案。我喜欢它,但它只为正整数给出了正确的答案:)。找到一种没有分支的方法来处理正数和负数的四舍五入将是一件有趣的事情。@halex假设2的comp和远离零舍五入的愿望,我想您应该对顶部位进行符号扩展(希望您的CPU架构可以在单符号右移中实现),XOR 0011 0010(即十进制50)在此基础上,添加一个符号位的实例(因此,有效地说,如果是正的,则添加0,如果是负的,则添加1),然后在除法之前将所有符号位添加到原始符号位,因为正整数为+50,负整数为-50。如果可以将有符号移位为进位,则可以通过进位为0的加法得到1或0加法。可能存在更简单的解决方案…
*(long*)&x
是未定义的行为(违反严格的别名规则)。而且,
long
不能保证与
double
的大小相同。也许你想要
memcpy
进入
int64\t
以安全地键入双关语?或者只使用
-(xfloat转换将为您生成0.0或-1.0。另外,请注意,
double
的值范围比
int64\u t
更宽,因此对于大于LONG\u MAX的数字,以这种方式舍入到整数将失败。如果您仍然使用C,实际上只需使用
nearbyint
rint
,并带有允许其内联的编译器选项即可对于x86-64:.或
lrint(x)
上的
roundsd
这样的单个指令,即使在没有SSE4.1的情况下,如果我们谈论的是x86-64.。但对于AArch64,
rint
nearbyint
内联到单个insn: