很难解释这个问题,我想将双精度数转换为整数而不将小数点后的值四舍五入。例如
double a = 123.456
我想转换成为
int b = 123456
我想知道有多少位,计算后将其移回123.456
PS:我只想要纯数学的方法来解决这个问题,不计算它的性质。
抱歉,您的问题无法解决,因为数字 123.456不作为双精度数存在。它被四舍五入为 123.4560000000000030695446184836328029632568359375,这个数字在去掉小数点后显然不适合任何整数类型。
如果您希望 123.456 被视为确切的数字 123.456,那么执行此操作的唯一远程简单方法是将其转换为字符串并从字符串中删除小数点。这可以通过类似的东西来实现
snprintf(buf, sizeof buf, "%.13f", 123.456);
但是,实际上要弄清楚要打印到的位置数量是相当困难的。如果你使用太多,你最终会得到我上面显示的部分确切值。如果你使用太少,那么显然你会放弃你想保留的地方。
如果您有文本"123.456"
,您可以简单地删除小数点并将生成的文本表示形式转换为整数值。如果您已经将文本转换为浮点值 ( double a = 123.456;
),那么所有的赌注都将被取消:浮点值没有预设的十进制位数,因为它表示为二进制小数。这有点像普通用法中的 1/3 与 .3333:它们没有相同的值,尽管我们通常假设 .3333 表示 1/3。
尝试这个 :
double a = 123.456;
int i;
char str[20];
char str2[20];
sptrintf(str,"%d",a);
for(i=0;i<strlen(str);i++)
{
if(!str[i] == '.')
{
sptrintf(str2,%c,str[i]);
}
}
int b = atoi(str2);
我相信做到这一点的规范方法是
#include <math.h>
#include <stdio.h>
int main()
{
double d = 123.456;
double int_part;
double fract_part;
fract_part = modf(d, &int_part);
int i = (int)int_part*1000 + (int)(fract_part*1000);
printf("%d", i);
}
其中文字 1000 是确定所需小数位数的常数。
将每次原始值乘以10^i,每次i增加直到abs(value' - abs(value')) < epsilon对于一个非常小的 epsilon。value'应该每次都从原始值计算,例如
value' = value * pow(10, i)
if ( abs(value' - abs(value')) < epsilon ) then stop
最初我建议你应该简单地乘以十,但正如 R.. 建议的那样,每次数值误差都会累积。结果,由于浮点数学,您可能会得到例如 epsilon = .0000001 的 123.456999 而不是 123.456000 的结果。
请注意,您可能会以这种方式超出 int 类型边界,并且可能还需要处理无穷大值。
正如 Ignacio Vazquez-Abrams 指出的那样,这可能会导致您想要将 123.500 转换为 123500 的场景出现问题。您可以通过首先添加一个非常小的值来解决它(它应该小于 epsilon)。但是,添加这样的值可能会导致数字错误。