今天在我的C ++编程课程中,我的proff告诉我,不应该直接比较两个浮点值。
所以我尝试了这段代码并找出了他陈述的原因。
{
"intents": [
{
"intent": "ActorIntent"
},
{
"slots": [
{
"name": "skill",
"type": "SKILL"
}
],
"intent": "SkillIntent"
}
}
我发现结果为94.89999999(一些相对误差)
我知道浮动数字不会以将其呈现给代码的方式存储。以二进制形式压缩那些零和零会涉及一些相对舍入误差。
我正在寻找两个问题的解决方案。 1.比较两个浮动值的有效方法。 2.如何将浮动值添加到另一个浮动值。例。添加0.1111到94.4345以获得准确值94.5456
提前致谢。
答案 0 :(得分:1)
- 比较两个浮动值的有效方法。
醇>
简单的double a,b; if (a == b)
是比较两个浮动值的有效方法。然而,正如OP所注意到的,这可能无法满足整体编码目标。更好的方法取决于比较的上下文,这不是OP提供的。见下文。
- 如何将浮动值添加到另一个浮动值。例。添加0.1111到94.4345以获得准确值94.5456
醇>
浮动值作为源代码具有有效的无限范围和精度,例如1.23456789012345678901234567890e1234567
。将此文本转换为double
通常限制为2个 64 不同值中的一个。选择最近的,但可能不完全匹配。
0.1111, 94.4345, 94.5456
都不能代表完全作为典型的double
。
1。)使用double, float
以外的其他类型。各种库提供十进制浮点类型。
2)将代码限制为支持double
到基础10表单的稀有平台,FLT_RADIX == 10
。
3)编写自己的代码,将"0.1111"
之类的用户输入处理到结构/字符串中,然后执行所需的操作。
4)将用户输入视为字符串并转换为某种整数类型,再次使用支持的例程来读取/计算/写入。
5)接受浮点运算在数学上不精确并处理舍入误差。
double a = 0.1111;
printf("a: %.*e\n", DBL_DECIMAL_DIG -1 , a);
double b = 94.4345;
printf("b: %.*e\n", DBL_DECIMAL_DIG -1 , b);
double sum = a + b;
printf("sum: %.*e\n", DBL_DECIMAL_DIG -1 , sum);
printf("%.4f\n", sum);
输出
a: 1.1110000000000000e-01
b: 9.4434500000000000e+01
sum: 9.4545599999999993e+01
94.5456 // Desired textual output based on a rounded `sum` to the nearest 0.0001
更多关于#1
如果没有寻找完全比较但是某种“两个值足够接近吗?”,则需要“足够接近”的定义 - 其中有很多。
以下“足够接近”通过检查两个数字的ULP来比较距离。当值处于相同的2的幂时,它是线性差异,而在其他方面变为对数。当然,改变标志是一个问题。
float
示例:
考虑从最负面到最正面排序的所有有限float
。以下有点可移植的代码为每个float
返回一个整数,其中相同的顺序。
uint32_t sequence_f(float x) {
union {
float f;
uint32_t u32;
} u;
assert(sizeof(float) == sizeof(uint32_t));
u.f = x;
if (u.u32 & 0x80000000) {
u.u32 ^= 0x80000000;
return 0x80000000 - u.u32;
}
return u.u3
}
现在,要确定两个float
是否“足够接近”,简单比较两个整数。
static bool close_enough(float x, float y, uint32_t ULP_delta) {
uint32_t ullx = sequence_f(x);
uint32_t ully = sequence_f(y);
if (ullx > ully) return (ullx - ully) <= ULP_delta;
return (ully - ullx) <= ULP_delta;
}
答案 1 :(得分:0)
我通常采用的方法是使用自定义相等比较功能。基本的想法是,你有一定的容忍度,比如0.0001或者其他什么。然后你减去你的两个数字并取其绝对值,如果它小于你的容差,你就把它视为平等。当然,还有其他策略可能更适合某些情况。
答案 2 :(得分:0)
为自己定义容差级别e
(例如e=.0001
)并检查abs(a-b) <= e
你不会得到一个&#34;确切的&#34;浮点值。永远。如果您事先知道您使用的是四位小数,并且您想要&#34;确切&#34;,那么您需要在内部将数字视为整数,并仅将它们显示为小数。 944345 + 1111 = 945456