C&C++   发布时间:2022-04-03  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了c – 如何“混合”两个值而不溢出?大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
虑以下功能

// Return a blended value of x and y:
//   blend(100,200,1,1) -> 150
//   blend(100,2,1) -> 133
uint8_t blend(uint8_t x,uint8_t y,uint8_t parts_x,uint8_t parts_y) {
  uint32_t big_parts_x = parts_x;
  uint32_t big_parts_y = parts_y;
  return (uint8_t) ((big_parts_x * x + big_parts_y * y) /
                    (big_parts_x + big_parts_y));
}

有没有办法接近适当的返回值而不需要任何大于uint8_t的分配?您可以通过执行两个分区轻松地将其分解(减少四舍五入)为两个uint16_t的添加.你能用uint8_t做到吗?

解决方法

符合标准的C实现保证执行至少16位的算术运算.

C standard第6.3.1.1p2节规定:

第E.1节还规定int必须能够支持至少在-3276732767范围内的值,而unsigned int必须支持至少在0到65535范围内的值.

由于uint8_t的排名低于int,因此当前者成为大多数运算符的主题时,前者将始终被提升为后者,包括,–,*和/.

鉴于此,您可以通过以下轻微修改安全地计算该值:

uint8_t blend(uint8_t x,uint8_t parts_y) {
    return ((1u*parts_x*X) / (parts_x + parts_y)) + ((1u*parts_y*y) / (parts_x + parts_y));
}

表达式parts_x * x和parts_y * y的最大值为65025.这对于16位int而言太大而不是16位无符号int,因此每个乘以1u以强制将值转换为unsigned int按照6.3.1.8节中规定的通常算术转换:

另请注意,我们将每个部分分别除以总和.如果我们在分割之前首先添加两个部分,则分子可能超过65535.通过首先进行除法,这会使每个子表达式回到uint8_t的范围内.然后我们可以添加两个部分,它们将再次位于uint8_t的范围内.

因此,上述表达式保证在符合C标准的编译器上返回正确的精确答案.

大佬总结

以上是大佬教程为你收集整理的c – 如何“混合”两个值而不溢出?全部内容,希望文章能够帮你解决c – 如何“混合”两个值而不溢出?所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。