2016-11-09 168 views
4


我需要分解一个数字的小数部分,但我需要得到最明显的表示。这里是我的代码,更清晰:
分解双精度小数部分

#include <stdio.h> 

void main(){ 
    double value = 0.123; 
    int decim_tab[6]; 
    int decimal; 
    int i; 

    for (i = 0; i < 6; ++i) { 
     value *= 10; 
     decimal = (int)value; 
     decim_tab[i] = decimal; 
     value -= decimal; 
    } 
    for (i = 0; i < 6; ++i) 
     print("%d\n", decim_tab[i]); 
} 

我需要的输出是:

1 
2 
3 
0 
0 
0 

,但我得到:

1 
2 
2 
9 
9 
9 

编辑

解决方案n个I发现是小的增量,以迫使最短表示添加到值:

#include <stdio.h> 

void main(){ 
    double value = 0.123; 
    int decim_tab[6]; 
    int decimal; 
    int i; 

    value += 0.000000001 
    for (i = 0; i < 6; ++i) { 
     value *= 10; 
     decimal = (int)value; 
     decim_tab[i] = decimal; 
     value -= decimal; 
    } 
    for (i = 0; i < 6; ++i) 
     print("%d\n", decim_tab[i]); 
} 

我会很高兴找到一个更好的办法,有什么建议?

+5

相关阅读:[?是浮点运算破(http://stackoverflow.com/q/588004/2305521) – fpg1503

+3

如何使用'的sprintf()',然后分析结果字符串? –

+4

您的'值+ = 0.000000001'解决方案不是解决方案。它会打破其他不会被破坏的数字。你的问题是,从*十进制*格式的浮点指针字面量转换为永远不能完全转换为*二进制*浮点数。如果你需要完美的分解,你不能使用浮点类型。 – user694733

回答

3

您得到意想不到的输出的原因是,小数部分不能总是用(最常见的)基数两个浮点数精确表示。在分配value后使用printf("%.20f", value);,您将看到值0.123实际上被存储为0.12299 ...,这就是您接收该输出的原因。

如果您只需要打印出六位数字,你可以使用浮点数的字符串格式化:

#include <stdio.h> 
#include <stdlib.h> 

int main(){ 
    double value = 0.123; 
    char *s = malloc(9); 

    sprintf(s++, "%.6f", value); 
    while(*s++){ 
     putchar(*s); 
     putchar('\n'); 
    } 
} 

编辑:在我的答案的代码是非常具体的,你给了,所以例如使用时它知道我做了一些假设,例如您的值在小数点之前永远不会超过一位数字。

1

如果您想要6位小数,您应该添加0.0000005(即0.5e-6)将值舍入到最近的位置。此方法适用于正数,首先提取符号,然后处理绝对值。

1

浮点数不是精确的值表示。这里有一个简单的例子:

double a = 0.15 + 0.15; // 0.15 + 0.15 == 0.3, right? 
double b = 0.1 + 0.2; // 0.1 + 0.2 == 0.3, right? 
if (a == b) { 
    printf("Equal\n"); 
} else { 
    printf("Unequal\n"); 
} 

这将打印什么? Equal?你确定?自己尝试一下:

http://rextester.com/VZOZ1043

它打印Unequal,那是因为有一些数字,浮点不能代表准确,这就是你总是需要记住做浮点运算时的东西。此外,许多操作都涉及到四舍五入,所以数学运算的结果尽可能好,但并不总是“确切”,如果您运行多个操作,也会有一个小小的错误。

double value = 0.123; 

// Assuming none of your numbers has more than 58 digits, 
// one period and one termination char. 
char buffer[60]; 

// Print the number to the buffer. 
// Missing: Error checking if it did fit! 
snprintf(buffer, sizeof(buffer), "%f", value); 

// Find the period or end of string 
int idx = 0; 
for (; buffer[idx] && buffer[idx] != '.'; idx++); 

// Print anything after the period till 
// the end of the string 
if (buffer[idx] == '.') { 
    for (idx++; buffer[idx]; idx++) { 
     printf("%c\n", buffer[idx]); 
    } 
} 

测试:http://rextester.com/CYDQO24769