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标准库,而不是第三方库?
-
您有充分的理由不能使用库吗?您将很难找到一个真正的便携式解决方案。
-
将Ecole 42及其规则违反使用我未编码的任何内容(有一些例外)
-
@spozzi因此,您不允许使用任何内置标头吗?
-
@spozzi如果是这样,那么您应该在问题中更清楚地说明您的限制。如果您真的不能使用标准标头(这是语言的内在部分),则如果您想做任何I / O一样多的代码,则该代码必须不可移植。
-
不"不使用我未编码的任何东西"的规则非常糟糕。 (并且您应该告诉我们该规则及其例外的确切用语,以便我们理解该规则。)int main(void)和int main(int argc, char *argv[])在C标准中给出,因此您没有编写这些代码,因此无法定义main?使用math.h的signbit宏绝对是测试浮点数符号的正确方法,它应该被视为一种基本的语言功能,而不是像使用其他人的代码那样不受限制。
-
如果您不能使用signbit,则没有完全可移植的正确解决方案。您可以将表示某些对象x的字节与表示-0.和0.的字节进行比较,并且在大多数实现中都可以使用(如果正确实现,则严格遵循C标准),但是可以可能具有?0和+0的多种表示形式,严格遵守C代码无法提供了解和区分它们的方法。
-
我不能使用任何图书馆。最好不要使用printf()然后...
-
相关:+0.0和-0.0上的哪些操作和函数给出不同的算术结果?
-
@AndrewHenle:我希望他们没有使用printf;问题的第一句话说他们正在实施。
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('+');
}
} |
-
"我不能使用任何图书馆。"
-
signbit是一个宏,因此不应要求链接任何库。演示版
-
@ jl2210:另一方面,fputc和朋友肯定需要stdio.h。而且,如果不使用stdarg.h,则几乎不可能实现诸如printf的varargs函数。因此,至少存在一部分标准库。 OP说有"某些例外";了解它们是有用的。
-
从OP正在实现的printf函数上的前缀ft_判断,可以判断他们没有可用的signbit宏。搜索libft或lib42以获得更多详细信息。
这类似于我完成的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);
} |
-
C是否保证所有可能的double表示形式都有正负无穷大?
-
@ThomasJager我这么认为。不过可能是IEEE。
-
@ThomasJager参见gnu.org/software/libc/manual/html_node/Infinity-and-NaN.html
-
" IEEE 754浮点数可以表示正无穷大"。
-
我不同意IEEE 754浮点类型可以处理它。我的观点是,如果不检查IEEE 754浮点数是否在使用中,这不是便携式解决方案。据我所知,C不保证任何给定的实现。
-
实际上,不,C不保证浮点类型具有任何无穷大的表示形式(正数或负数)。它们通常会这样做,因为IEEE 754表示形式和算法相当普遍,但是C不需要这些。
-
但是,这肯定比(*((long *)&a) == 0x8000000000000000)更可移植。
-
@ThomasJager查看更新。
-
@JohnBollinger查看更新。
-
@chux请参阅更新。现在两者都是isPositiveZero。