为什么同一个数的sin return 是两个截然不同的值?
Why does sin of the same number return two very different values?
有人可以解释为什么这两个输出有很大不同吗?
当我打印出 (float)direction*PI/180.0f
和 theta
时,它们的计算结果都如预期的那样为 1.5708。为什么在将其放入 sin
函数之前将其放入 float 变量会使输出产生如此巨大的差异?另请注意 test2
returns 正确答案 (1),而 test
returns 错误答案 (0)。
#include <iostream>
#include <cmath>
#define PI 3.14159265
int main()
{
int direction = 90;
float theta = (float)direction*PI/180.0f;
int test = (int)sin(theta);
int test2 = (int)sin((float)direction*PI/180.0f);
std::cout << theta << " " << (float)direction*PI/180.0f << " " << test << " " << test2;
}
舍入错误。
您的测试变量 < 1.0,您的 test2 变量 >= 1.0。
I C 和 C++,0.9999999999999 四舍五入为 0。
#include <iostream>
#include <cmath>
#define PI 3.14159265
int main()
{
int direction = 90;
float theta = (float)direction*PI/180.0f;
auto test = sin(theta);
auto test2 = sin((float)direction*PI/180.0f);
std::cout << theta << " " << (float)direction*PI/180.0f << " " << (int) test << " " << (int) test2 << std::endl;
std::cout <<std::boolalpha << "test >= 1.0 = " << (test >= 1.0) << std::endl;
std::cout << "test2 >= 1.0 = " << (test2 >= 1.0) << std::endl;
std::cout << "test == test2 = " << (test == test2) << std::endl;
std::cout << "test < test2 = " << (test < test2) << std::endl;
}
输出:
1.5708 1.5708 0 1
test >= 1.0 = false
test2 >= 1.0 = true
test == test2 = false
test < test2 = true
(float)direction*PI/180.0f
使用 double
算术。 PI
是一个 double
文字,因为它没有 f
后缀。其他两个操作数((float)direction
和 180.0f
)是 float
,是的,但它们只是被提升为 double
(并且转换在 IEEE 浮点数中是精确的)。请注意,由于运算符优先级,(float)
仅适用于 direction
。对于 test2
,您将结果 double
直接传递给 sin
,并且 sin
return 正好是 1
。对于 test
,您首先在对 theta
的赋值中将 double
向下转换为 float
,然后将其向上转换为 double
以便调用sin
(请注意,您调用的是 C 的 double sin(double)
,而不是 C++ 的 float std::sin(float)
)。通过转换,theta
失去了一些四舍五入的价值。 sin
然后给出一个相应地比 1
小一点的值,然后在转换为 int
时一直舍入到 0
。如果你调用了 std::sin
,那么你会得到 1
,因为 std::sin
会将略小于 1
double
的值四舍五入为 float
,这将给出 1
(与截断为 int
不同)。
像这样将浮点值打印到 std::cout
对于调试浮点没有用,因为值会四舍五入。我喜欢使用 std::hexfloat
,它显示 真实 二进制值(转换为十六进制),而不是十进制谎言。我还摆脱了 PI
并将 C 风格的强制转换转换为函数式强制转换,以更清楚地显示正在发生的事情。我已经将 test
和 test2
变成了 double
s(sin
的 return 类型)所以我们可以真正地看看它们。
int main() {
int direction = 90;
float theta = float(direction)*3.14159265/180.0f;
double test1 = sin(theta);
double test2 = sin(float(direction)*3.14159265/180.0f);
std::cout << std::hexfloat;
std::cout << theta << " " << float(direction)*3.14159265/180.0f << "\n";
std::cout << test1 << " " << test2 << "\n";
}
给出
0x1.921fb6p+0 0x1.921fb53c8d4fp+0
0x1.ffffffffffff7p-1 0x1p+0
这巧妙地向我们展示了我们在 test2
中使用的值比 theta
有更多的位数,因为它是 double
而不是 float theta
。您还看到 test1
几乎是 1
,但不完全是。
有人可以解释为什么这两个输出有很大不同吗?
当我打印出 (float)direction*PI/180.0f
和 theta
时,它们的计算结果都如预期的那样为 1.5708。为什么在将其放入 sin
函数之前将其放入 float 变量会使输出产生如此巨大的差异?另请注意 test2
returns 正确答案 (1),而 test
returns 错误答案 (0)。
#include <iostream>
#include <cmath>
#define PI 3.14159265
int main()
{
int direction = 90;
float theta = (float)direction*PI/180.0f;
int test = (int)sin(theta);
int test2 = (int)sin((float)direction*PI/180.0f);
std::cout << theta << " " << (float)direction*PI/180.0f << " " << test << " " << test2;
}
舍入错误。 您的测试变量 < 1.0,您的 test2 变量 >= 1.0。 I C 和 C++,0.9999999999999 四舍五入为 0。
#include <iostream>
#include <cmath>
#define PI 3.14159265
int main()
{
int direction = 90;
float theta = (float)direction*PI/180.0f;
auto test = sin(theta);
auto test2 = sin((float)direction*PI/180.0f);
std::cout << theta << " " << (float)direction*PI/180.0f << " " << (int) test << " " << (int) test2 << std::endl;
std::cout <<std::boolalpha << "test >= 1.0 = " << (test >= 1.0) << std::endl;
std::cout << "test2 >= 1.0 = " << (test2 >= 1.0) << std::endl;
std::cout << "test == test2 = " << (test == test2) << std::endl;
std::cout << "test < test2 = " << (test < test2) << std::endl;
}
输出:
1.5708 1.5708 0 1
test >= 1.0 = false
test2 >= 1.0 = true
test == test2 = false
test < test2 = true
(float)direction*PI/180.0f
使用 double
算术。 PI
是一个 double
文字,因为它没有 f
后缀。其他两个操作数((float)direction
和 180.0f
)是 float
,是的,但它们只是被提升为 double
(并且转换在 IEEE 浮点数中是精确的)。请注意,由于运算符优先级,(float)
仅适用于 direction
。对于 test2
,您将结果 double
直接传递给 sin
,并且 sin
return 正好是 1
。对于 test
,您首先在对 theta
的赋值中将 double
向下转换为 float
,然后将其向上转换为 double
以便调用sin
(请注意,您调用的是 C 的 double sin(double)
,而不是 C++ 的 float std::sin(float)
)。通过转换,theta
失去了一些四舍五入的价值。 sin
然后给出一个相应地比 1
小一点的值,然后在转换为 int
时一直舍入到 0
。如果你调用了 std::sin
,那么你会得到 1
,因为 std::sin
会将略小于 1
double
的值四舍五入为 float
,这将给出 1
(与截断为 int
不同)。
像这样将浮点值打印到 std::cout
对于调试浮点没有用,因为值会四舍五入。我喜欢使用 std::hexfloat
,它显示 真实 二进制值(转换为十六进制),而不是十进制谎言。我还摆脱了 PI
并将 C 风格的强制转换转换为函数式强制转换,以更清楚地显示正在发生的事情。我已经将 test
和 test2
变成了 double
s(sin
的 return 类型)所以我们可以真正地看看它们。
int main() {
int direction = 90;
float theta = float(direction)*3.14159265/180.0f;
double test1 = sin(theta);
double test2 = sin(float(direction)*3.14159265/180.0f);
std::cout << std::hexfloat;
std::cout << theta << " " << float(direction)*3.14159265/180.0f << "\n";
std::cout << test1 << " " << test2 << "\n";
}
给出
0x1.921fb6p+0 0x1.921fb53c8d4fp+0
0x1.ffffffffffff7p-1 0x1p+0
这巧妙地向我们展示了我们在 test2
中使用的值比 theta
有更多的位数,因为它是 double
而不是 float theta
。您还看到 test1
几乎是 1
,但不完全是。