关于C#:如何区分零和负零?

How can I differentiate between zero and negative zero?

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

我检查负性的条件就是" x <0",这不包括我的问题。 我发现了区分零和负零的有希望的解决方案。

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

1
2
3
double a = -0.0;
printf("%d
"
, (*((long *)&a) == 0x8000000000000000));

我希望该程序打印1,但是在我的程序中,当我在代码中执行它时,它会输出0。 我有一个问题理解的部分是如何做到的:*((long *)&a)使一个数字可与十六进制对应的数字相提并论。


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

例:

1
2
3
4
5
6
7
8
9
10
#include <math.h>
#include <stdio.h>

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


这类似于我完成的Codewars Kata。诀窍是将要检查的数字除以负零,如下所示:

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

如果a为负零,则除法给出-infinity,如果a为零,则除法给出infinity

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

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

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

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

1
2
3
4
5
#include <math.h>

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