舍入浮点数的源代码
Posted
技术标签:
【中文标题】舍入浮点数的源代码【英文标题】:Source code to round floating point number 【发布时间】:2014-04-03 11:28:08 【问题描述】:除了使用ceil
和floor
之类的任何内置函数之外,如何舍入浮点数?
我想将 2.10 转换为 2.14-> 2.1 和 2.15 转换为 2.19 -> 2.2
我写了一些逻辑,但卡在中间
float a = 2.24;
int b = a*100;
int result n, i =0;
while(i>2)
n = b%10;
i++;
if(n >5)
c = b%10;
c = c/10 + 1;
我尝试了很多内置函数,但所有这些都不适用于我的 diab 编译器
// totalDist = roundf(totalDist * 10) / 10.0;
// totalDist = floor(totalDist * pow(10., 1) + .5) / pow(10., 1);
totalDist = floorf(totalDist * 10 + 0.5) / 10;
打算自己写逻辑
【问题讨论】:
为什么“除了使用任何内置函数”?totalDist = floorf(totalDist * 10 + 0.5) / 10;
似乎是正确的,但您可以使用浮点类型文字:10.0f
和 0.5f
。
【参考方案1】:
float a = 2.24;
float b = roundf(a*10.0f)/10.0f;//roundf in C99
【讨论】:
+1 对于 1) 适用于正数和负数的解决方案,2) 不限于int
范围和 3) 是精确的。 (建议使用 10.0f 而不是 10.0)。
@chux 我按照你的提议改了。
@Kerrek SB 我曾经也这么认为。我对 C 规范的评论没有找到支持。它似乎取决于FLT_EVAL_METHOD
。如果为 0,则“仅根据类型的范围和精度评估所有操作和常量;”如果为 1,则“将 float 和 double 类型的操作和常量评估为 double 类型的范围和精度......”。存在其他设置。
@chux:你是对的,没关系 - 算术转换允许两个操作数都是浮点数。【参考方案2】:
试试int((x + 0.05) * 10.0) / 10.0
。
您也可以使用trunc
,而不是与int
之间的转换。
或者你可以使用round
:round(x * 10.0) / 10.0
【讨论】:
int()
将在整数范围外失败。 trunc()
将在负数上失败。您可以改用floor()
。
@Vovanium:在整数范围之外,浮点数也没有子单位精度。 OP 没有指定负数的行为,但这确实有待决定。
首先,标准将最小整数范围定义为 -32767..32767,它小于大多数可用的浮点精度。其次,即使对于大数(例如 1E10),舍入也是不可能的,函数可以返回正确的值,而不是溢出。【参考方案3】:
因为我的旧答案需要大量仔细编程才能使其发挥作用
我提出了另一种实现轮函数的方法:
您可以轻松检查(正/负)数字是否会四舍五入 或下降(加/减)0.5。然后你可以截断结果 并接受你的答案。此外,为了支持更深层次的轮作为 你想要你可以让用户指定多少位小数 想要,瞧:
long double round_f(long double number, int decimal_places)
assert(decimal_places > 0);
double power = pow(10, decimal_places-1);
number *= power;
return (number >= 0) ? ((long long)(number + 0.5))/power : ((long long)(number - 0.5))/power;
And here you can see a working example.
旧的:
你可以使用冲刺:
#include <stdio.h>
int main(void)
float a = 2.24;
int size;
char num[8] = 0;
sprintf(num, "%d", (int) (a * 100));
for (size=0; num[size]; size++);
size--;
if (num[size] < '5')
num[size] = '0';
else
num[size] = '0';
if (num[size-1] == '9')
num[size-1] = '0';
else
num[size-1]++;
printf("a = %f\n", a);
printf("num = %s\n", num);
return(0);
你可以看到逻辑。最后,您可以将字符串恢复为整数并乘以 100。
编辑:这只是逻辑。请参阅下面的 cmets,了解完全工作所需的条件。
【讨论】:
最终数字为 220,实际结果预期为 2.3 此方法对a > 100000.0
失败。对于像3.99
这样的数字,它会失败。它失败了a < -10000.0
。 a*100
超大 int
范围失败。
是的。我知道。我只想展示它背后的逻辑。您可以轻松地用循环替换检查 9 的嵌套 if。您还可以使字符数组更大,数字更大。您也可以将第一个位置留空以避免“溢出”(对于像 99.99 这样的情况下的进位)。
同意这是一个方法背后的逻辑的一般演示,而不是一个完整的解决方案:(float --> int --> sprintf --> char processing --> 隐蔽回浮动) .断言它“可以轻松替换”,但不发布掩盖了微妙问题:有限的int
范围、字符缓冲区溢出、算术溢出处理。
@chux 我更改了答案以满足您的标准,我相信。你怎么看?感谢 cmets。【参考方案4】:
如果您只是想将数字四舍五入以用于输出目的,那么%.1f
格式字符串确实是正确答案。
printf("%.1f", 2.14);
或 如果你真的想四舍五入,那么像这样的工作
#include <math.h>
float val = 37.777779;
float rounded_down = floorf(val * 100) / 100; /* Result: 37.77 */
float nearest = floorf(val * 100 + 0.5) / 100; /* Result: 37.78 */
float rounded_up = ceilf(val * 100) / 100; /* Result: 37.78 */
通常我们使用nearest
方法
【讨论】:
注意:floorf(val * 100 + 0.5)
对负数失败。【参考方案5】:
BLUEPIXY 的回答很好。但总的来说;浮点乘法比除法快,所以如果速度是相关的;乘以 0.1 而不是除以 10。
【讨论】:
我尝试了所有这些 // totalDist = roundf(totalDist * 10) / 10.0; // totalDist = floor(totalDist * pow(10., 1) + .5) / pow(10., 1); totalDist = floorf(totalDist * 10 + 0.5) / 10;以上是关于舍入浮点数的源代码的主要内容,如果未能解决你的问题,请参考以下文章