如何区分零和负零?

时间:2019-08-08 16:57:19

标签: c floating-point binary hex

我正在实现printf()函数。几乎所有东西都可以正常工作,但是当被称为ft_printf("%f", -0.0)时我遇到了问题。我的程序输出0.0而不是-0.0。我不能使用任何库。

我检查负性的条件只是“ x <0”,不包括我的问题。我在Distinguish zero and negative zero中找到了一个有前途的解决方案。

这似乎可以解决我的问题:

double a = -0.0;
printf("%d\n", (*((long *)&a) == 0x8000000000000000));

我希望该程序打印1,但是在我的程序中,当我在代码中执行此操作时,它会输出0。我对此有一个问题的理解是:*((long *)&a)使得数字可以与十六进制的数字相媲美。

2 个答案:

答案 0 :(得分:7)

C数学库(标准库的一部分)提供a signbit macro,这绝对是检查浮点数符号的最简单,最可移植的方法。如果您要避免使用库的要求是第三方库,那么它将满足您的目的。

示例:

#include <math.h>
#include <stdio.h>

void putsign(double d) {
    if (signbit(d)) {
        putchar('-');
    } else {
        putchar('+');
    }
}

答案 1 :(得分:2)

这类似于我完成的Codewars Kata。诀窍是将要检查的数字除以负零,就像这样:

int isPositiveZero(double a) {
    return 1/a == 1/0.0;
}

如果-infinity为负零,则除法得到a,如果infinity为零,则除法得到a

如果您想按照自己的方式做,请尝试以下操作:

(*((long *)&a) & 0x8000000000000000)

请注意,这违反了严格的别名规则,这会导致未定义的行为。这意味着您的程序可以执行任何操作,从打印正确的结果到使计算机发芽并飞走。

如果您有math.h可用,并且不反对使用标准C库中的宏,那么此解决方案(使用signbit)也可以使用(并且更加可移植):

#include <math.h>

int isPositiveZero(double a) {
    return a == 0.0 && !signbit(a);
}