我正在尝试编写一个程序,该程序将在基数10中使用浮点数,并在基数2中转换其小数部分。在以下代码中,我打算将转换函数调用为printf,并格式化输出;我遇到的问题在于我的fra_binary(),在这里我想不出最好的方法来分别返回由转换结果组成的整数(串联)。这是我现在所做的事情(由于我仍在处理代码,因此未对代码进行优化):
#include <stdio.h>
#include <math.h>
int fra_binary(double fract) ;
int main()
{
long double n ;
double fract, deci ;
printf("base 10 :\n") ;
scanf("%Lf", &n) ;
fract = modf(n, &deci) ;
int d = deci ;
printf("base 2: %d.%d\n", d, fra_binary(fract)) ;
return(0) ;
}
int fra_binary(double F)
{
double fl ;
double decimal ;
int array[30] ;
for (int i = 0 ; i < 30 ; i++) {
fl = F * 2 ;
F = modf(fl, &decimal) ;
array[i] = decimal ;
if (F == 0) break ;
}
return array[0] ;
}
显然,这部分返回了所需的输出,因为我需要将整个数组串联为一个int或char来显示所需的1和0系列。因此,在每一回合中,我都想将要处理的数字的小数部分用作要连接的二进制数字(1 + 0 = 10而不是1)。我将如何处理? 希望这有道理!
答案 0 :(得分:0)
return array[0] ;
仅是int array[30]
中设置的fra_binary()
的第一个值。代码将丢弃除循环for (int i = 0 ; i < 30 ; i++)
的第一次计算以外的所有内容。
将其小数部分转换为基数2
OP的循环思想是一个很好的起点。然而,int array[30]
不足以将所有double
的小数部分编码为“二进制”。
找不到返回整数的最佳方法
返回int
是不够的。而是考虑使用字符串-或以同样的方式管理整数数组。
使用<float.h>
中的定义来驱动缓冲区要求。
#include <stdio.h>
#include <math.h>
#include <float.h>
char *fra_binary(char *dest, double x) {
_Static_assert(FLT_RADIX == 2, "Unexpected FP base");
double deci;
double fract = modf(x, &deci);
fract = fabs(fract);
char *s = dest;
do {
double d;
fract = modf(fract * 2.0, &d);
*s++ = "01"[(int) d];
} while (fract);
*s = '\0';
// For debug
printf("%*.*g --> %.0f and .", DBL_DECIMAL_DIG + 8, DBL_DECIMAL_DIG, x,
deci);
return dest;
}
int main(void) {
// Perhaps 53 - -1021 + 1
char fraction_string[DBL_MANT_DIG - DBL_MIN_EXP + 1];
puts(fra_binary(fraction_string, -0.0));
puts(fra_binary(fraction_string, 1.0));
puts(fra_binary(fraction_string, asin(-1))); // machine pi
puts(fra_binary(fraction_string, -0.1));
puts(fra_binary(fraction_string, DBL_MAX));
puts(fra_binary(fraction_string, DBL_MIN));
puts(fra_binary(fraction_string, DBL_TRUE_MIN));
}
输出
-0 --> -0 and .0
1 --> 1 and .0
3.1415926535897931 --> 3 and .001001000011111101101010100010001000010110100011
-0.10000000000000001 --> -0 and .0001100110011001100110011001100110011001100110011001101
1.7976931348623157e+308 --> 179769313486231570814527423731704356798070600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 and .0
2.2250738585072014e-308 --> 0 and .00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
4.9406564584124654e-324 --> 0 and .000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
也不清楚为什么输入为long double
,但处理仍为double
。建议仅使用一种FP类型。
答案 1 :(得分:0)
请注意,您的算法会先找出分数最高有效位的二进制表示形式。
将小数部分转换为二进制字符串的一种方法是,为函数提供一个字符串和一个字符串长度,并让该函数最多填充许多二进制数字:
true
以上函数的工作方式与snprintf()
非常相似,不同的是它仅占用/* This function returns the number of chars needed in dst
to describe the fractional part of value in binary,
not including the trailing NUL ('\0').
Returns zero in case of an error (non-finite value).
*/
size_t fractional_bits(char *dst, size_t len, double value)
{
double fraction, integral;
size_t i = 0;
if (!isfinite(value))
return 0;
if (value > 0.0)
fraction = modf(value, &integral);
else
if (value < 0.0)
fraction = modf(-value, &integral);
else {
/* Zero fraction. */
if (len > 1) {
dst[0] = '0';
dst[1] = '\0';
} else
if (len > 0)
dst[0] = '\0';
/* One binary digit was needed for exact representation. */
return 1;
}
while (fraction > 0.0) {
fraction = fraction * 2.0;
if (fraction >= 1.0) {
fraction = fraction - 1.0;
if (i < len)
dst[i] = '1';
} else
if (i < len)
dst[i] = '0';
i++;
}
if (i < len)
dst[i] = '\0';
else
if (len > 0)
dst[len - 1] = '\0';
return i;
}
,其小数位将被存储为一串二进制数字(double
或{{1} }。并在发生错误(非限定0
值)的情况下返回1
。
另一个选择是使用无符号整数类型来保存位。例如,如果您的代码打算在0
是IEEE-754 Binary64类型或类似的体系结构上工作,则尾数的精度最高为53位,而double
就足够了。>
这是一个例子:
double
返回值是小数部分的二进制表示形式:[i] fractional_part [/ i]≈[i] result [/ i] / 2 [sup] [i] bits [/ i] [/ sup], [i]位[/ i]在1到64之间(包括1和64)。
为了使调用者能够检测到错误,如果没有发生错误,该函数会将uint64_t
清除为零。如果确实发生错误,则该函数将返回零,并且uint64_t fractional_bits(const double val, size_t bits)
{
double fraction, integral;
uint64_t result = 0;
if (bits < 1 || bits > 64) {
errno = EINVAL;
return 0;
}
if (!isfinite(val)) {
errno = EDOM;
return 0;
}
if (val > 0.0)
fraction = modf(val, &integral);
else
if (val < 0.0)
fraction = modf(-val, &integral);
else {
errno = 0;
return 0;
}
while (bits-->0) {
result = result << 1;
fraction = fraction * 2.0;
if (fraction >= 1.0) {
fraction = fraction - 1.0;
result = result + 1;
}
}
errno = 0;
return result;
}
的值不是有限的,则将errno
设置为errno
;如果EDOM
的值小于1或大于0,则函数将返回EINVAL
。 64。
如果实现任意大小的无符号整数类型或位图类型,则可以将两种方法结合使用。