double/float C 中的转换
double/float conversion in C
我有这个代码
#define Third (1.0/3.0)
#define ThirdFloat (1.0f/3.0f)
int main()
{
double a=1/3;
double b=1.0/3.0;
double c=1.0f/3.0f;
printf("a = %20.15lf, b = %20.15lf, c = %20.15lf\n", a,b,c);
float d=1/3;
float e=1.0/3.0;
float f=1.0f/3.0f;
printf("d = %20.15f, e = %20.15f, f = %20.15f\n", d,e,f);
double g=Third*3.0;
double h=ThirdFloat*3.0;
float i=ThirdFloat*3.0f;
printf("(1/3)*3: g = %20.15lf; h = %20.15lf, i = %20.15f\n", g, h, i);
}
给出输出
a = 0.000000000000000, b = 0.333333333333333, c = 0.333333343267441
d = 0.000000000000000, e = 0.333333343267441, f = 0.333333343267441
(1/3)*3: g = 1.000000000000000; h = 1.000000029802322, i = 1.000000000000000
我假设 a
和 d
的输出看起来像这样,因为编译器在除法后将整数值转换为浮点数。
b
看起来不错,e
是错误的,因为 float
精度低,因此 c
和 f
.
但我不知道为什么 g
具有正确的值(我认为 1.0/3.0 = 1.0lf/3.0lf
,但 i
应该是错误的)以及为什么 h
不是与 i
.
相同
但我不知道为什么 g 有正确的值(我认为 1.0/3.0 = 1.0lf/3.0lf
G 的值恰好应基于:
#define Third (1.0/3.0)
...
double g=Third*3.0;
即 g=(1.0/3.0)*3.0;
即 1.000000000000000
(当使用 "%20.15lf"
打印时)
让我们先仔细看看:使用 "%.17e"
(近似十进制)和 "%a"
(精确)。
#define Third (1.0/3.0)
#define ThirdFloat (1.0f/3.0f)
#define FMT "%.17e, %a"
int main(void) {
double a=1/3;
double b=1.0/3.0;
double c=1.0f/3.0f;
printf("a = " FMT "\n", a,a);
printf("b = " FMT "\n", b,b);
printf("c = " FMT "\n", c,c);
puts("");
float d=1/3;
float e=1.0/3.0;
float f=1.0f/3.0f;
printf("d = " FMT "\n", d,d);
printf("e = " FMT "\n", e,e);
printf("f = " FMT "\n", f,f);
puts("");
double g=Third*3.0;
double h=ThirdFloat*3.0;
float i=ThirdFloat*3.0f;
printf("g = " FMT "\n", g,g);
printf("h = " FMT "\n", h,h);
printf("i = " FMT "\n", i,i);
}
输出
a = 0.00000000000000000e+00, 0x0p+0
b = 3.33333333333333315e-01, 0x1.5555555555555p-2
c = 3.33333343267440796e-01, 0x1.555556p-2
d = 0.00000000000000000e+00, 0x0p+0
e = 3.33333343267440796e-01, 0x1.555556p-2
f = 3.33333343267440796e-01, 0x1.555556p-2
g = 1.00000000000000000e+00, 0x1p+0
h = 1.00000002980232239e+00, 0x1.0000008p+0
i = 1.00000000000000000e+00, 0x1p+0
But i have no idea why g has correct value
(1.0/3.0)*3.0
可以在编译器或 运行 时评估为 double
,并且 rounded 结果正好是 1.0 .
(1.0/3.0)*3.0
可以在编译器或 运行 时使用比 double
更宽的数学计算,四舍五入的结果正好是 1.0。研究 FLT_EVAL_METHOD
.
and why h isn't the same as i.
(1.0f/3.0f)
可以使用 float
数学来形成与 one-third 明显不同的 float
商:0.333333343267.... 最后的 *3.0
与 1.0.
没有什么不同
输出都是正确的。我们需要看看为什么期望不对。
OP 进一步问道:“为什么 h
(float * double
) 不如 i
(float * float
) 准确?”
两者都以 0.333333343267... * 3.0
开头,而不是 one-third * 3.0
。
float * double
更 准确。两者形成一个乘积,但 float * float
是一个 float
乘积 四舍五入 到 224 中最接近的 1 部分,而更准确的 float * double
产品是 double
和 轮 到 253 中最接近的 1 部分。 float * float
舍入为 1.0000000 而 float * double
舍入为 1.0000000298...
我想我找到了答案。
#define Third (1.0/3.0)
#define ThirdFloat (1.0f/3.0f)
printf("%20.15f, %20.15lf\n", ThirdFloat*3.0, ThirdFloat*3.0);//float*double
printf("%20.15f, %20.15lf\n", ThirdFloat*3.0f, ThirdFloat*3.0f);//float*float
printf("%20.15f, %20.15lf\n", Third*3.0, Third*3.0);//double*double
printf("%20.15f, %20.15lf\n\n", Third*3.0f, Third*3.0f);//float*float
printf("%20.15f, %20.15lf\n", Third, Third);
printf("%20.15f, %20.15lf\n", ThirdFloat, ThirdFloat);
printf("%20.15f, %20.15lf\n", 3.0, 3.0);
printf("%20.15f, %20.15lf\n", 3.0f, 3.0f);
并输出:
1.000000029802322, 1.000000029802322
1.000000000000000, 1.000000000000000
1.000000000000000, 1.000000000000000
1.000000000000000, 1.000000000000000
0.333333333333333, 0.333333333333333
0.333333343267441, 0.333333343267441
3.000000000000000, 3.000000000000000
3.000000000000000, 3.000000000000000
由于浮动的限制,第一行不准确。常量 ThirdFloat
的精度非常低,因此当乘以 double
时,编译器采用这个非常糟糕的近似值 (0.333333343267441
),将其转换为 double
并乘以 3.0
由 double
给出,这也给出了错误的结果 (1.000000029802322
)。
但是如果 ThirdFloat
,也就是 float
,乘以 3.0f
,也就是 float
,编译器可以通过取 float
的精确值来避免近似=23=] 并将其乘以 3
,这就是我得到准确结果的原因。
我有这个代码
#define Third (1.0/3.0)
#define ThirdFloat (1.0f/3.0f)
int main()
{
double a=1/3;
double b=1.0/3.0;
double c=1.0f/3.0f;
printf("a = %20.15lf, b = %20.15lf, c = %20.15lf\n", a,b,c);
float d=1/3;
float e=1.0/3.0;
float f=1.0f/3.0f;
printf("d = %20.15f, e = %20.15f, f = %20.15f\n", d,e,f);
double g=Third*3.0;
double h=ThirdFloat*3.0;
float i=ThirdFloat*3.0f;
printf("(1/3)*3: g = %20.15lf; h = %20.15lf, i = %20.15f\n", g, h, i);
}
给出输出
a = 0.000000000000000, b = 0.333333333333333, c = 0.333333343267441
d = 0.000000000000000, e = 0.333333343267441, f = 0.333333343267441
(1/3)*3: g = 1.000000000000000; h = 1.000000029802322, i = 1.000000000000000
我假设 a
和 d
的输出看起来像这样,因为编译器在除法后将整数值转换为浮点数。
b
看起来不错,e
是错误的,因为 float
精度低,因此 c
和 f
.
但我不知道为什么 g
具有正确的值(我认为 1.0/3.0 = 1.0lf/3.0lf
,但 i
应该是错误的)以及为什么 h
不是与 i
.
但我不知道为什么 g 有正确的值(我认为 1.0/3.0 = 1.0lf/3.0lf
G 的值恰好应基于:
#define Third (1.0/3.0)
...
double g=Third*3.0;
即 g=(1.0/3.0)*3.0;
即 1.000000000000000
(当使用 "%20.15lf"
打印时)
让我们先仔细看看:使用 "%.17e"
(近似十进制)和 "%a"
(精确)。
#define Third (1.0/3.0)
#define ThirdFloat (1.0f/3.0f)
#define FMT "%.17e, %a"
int main(void) {
double a=1/3;
double b=1.0/3.0;
double c=1.0f/3.0f;
printf("a = " FMT "\n", a,a);
printf("b = " FMT "\n", b,b);
printf("c = " FMT "\n", c,c);
puts("");
float d=1/3;
float e=1.0/3.0;
float f=1.0f/3.0f;
printf("d = " FMT "\n", d,d);
printf("e = " FMT "\n", e,e);
printf("f = " FMT "\n", f,f);
puts("");
double g=Third*3.0;
double h=ThirdFloat*3.0;
float i=ThirdFloat*3.0f;
printf("g = " FMT "\n", g,g);
printf("h = " FMT "\n", h,h);
printf("i = " FMT "\n", i,i);
}
输出
a = 0.00000000000000000e+00, 0x0p+0
b = 3.33333333333333315e-01, 0x1.5555555555555p-2
c = 3.33333343267440796e-01, 0x1.555556p-2
d = 0.00000000000000000e+00, 0x0p+0
e = 3.33333343267440796e-01, 0x1.555556p-2
f = 3.33333343267440796e-01, 0x1.555556p-2
g = 1.00000000000000000e+00, 0x1p+0
h = 1.00000002980232239e+00, 0x1.0000008p+0
i = 1.00000000000000000e+00, 0x1p+0
But i have no idea why g has correct value
(1.0/3.0)*3.0
可以在编译器或 运行 时评估为double
,并且 rounded 结果正好是 1.0 .(1.0/3.0)*3.0
可以在编译器或 运行 时使用比double
更宽的数学计算,四舍五入的结果正好是 1.0。研究FLT_EVAL_METHOD
.
and why h isn't the same as i.
(1.0f/3.0f)
可以使用 float
数学来形成与 one-third 明显不同的 float
商:0.333333343267.... 最后的 *3.0
与 1.0.
输出都是正确的。我们需要看看为什么期望不对。
OP 进一步问道:“为什么 h
(float * double
) 不如 i
(float * float
) 准确?”
两者都以 0.333333343267... * 3.0
开头,而不是 one-third * 3.0
。
float * double
更 准确。两者形成一个乘积,但 float * float
是一个 float
乘积 四舍五入 到 224 中最接近的 1 部分,而更准确的 float * double
产品是 double
和 轮 到 253 中最接近的 1 部分。 float * float
舍入为 1.0000000 而 float * double
舍入为 1.0000000298...
我想我找到了答案。
#define Third (1.0/3.0)
#define ThirdFloat (1.0f/3.0f)
printf("%20.15f, %20.15lf\n", ThirdFloat*3.0, ThirdFloat*3.0);//float*double
printf("%20.15f, %20.15lf\n", ThirdFloat*3.0f, ThirdFloat*3.0f);//float*float
printf("%20.15f, %20.15lf\n", Third*3.0, Third*3.0);//double*double
printf("%20.15f, %20.15lf\n\n", Third*3.0f, Third*3.0f);//float*float
printf("%20.15f, %20.15lf\n", Third, Third);
printf("%20.15f, %20.15lf\n", ThirdFloat, ThirdFloat);
printf("%20.15f, %20.15lf\n", 3.0, 3.0);
printf("%20.15f, %20.15lf\n", 3.0f, 3.0f);
并输出:
1.000000029802322, 1.000000029802322
1.000000000000000, 1.000000000000000
1.000000000000000, 1.000000000000000
1.000000000000000, 1.000000000000000
0.333333333333333, 0.333333333333333
0.333333343267441, 0.333333343267441
3.000000000000000, 3.000000000000000
3.000000000000000, 3.000000000000000
由于浮动的限制,第一行不准确。常量 ThirdFloat
的精度非常低,因此当乘以 double
时,编译器采用这个非常糟糕的近似值 (0.333333343267441
),将其转换为 double
并乘以 3.0
由 double
给出,这也给出了错误的结果 (1.000000029802322
)。
但是如果 ThirdFloat
,也就是 float
,乘以 3.0f
,也就是 float
,编译器可以通过取 float
的精确值来避免近似=23=] 并将其乘以 3
,这就是我得到准确结果的原因。