【发布时间】:2021-11-26 20:13:18
【问题描述】:
我试图从math.h 中了解有关sin 和sinf 的一些信息。
我知道它们的类型不同:前者接受并返回doubles,后者接受并返回floats。
但是,如果我使用 float 参数调用 sin,GCC 仍会编译我的代码:
#include <stdio.h>
#include <math.h>
#define PI 3.14159265
int main ()
{
float x, result;
x = 135 / 180 * PI;
result = sin (x);
printf ("The sin of (x=%f) is %f\n", x, result);
return 0;
}
默认情况下,所有编译都很好(即使使用 -Wall、-std=c99 和 -Wpedantic;我需要使用 C99)。 GCC 不会抱怨我将浮点数传递给sin。如果我启用-Wconversion,那么 GCC 会告诉我:
warning: conversion to ‘float’ from ‘double’ may alter its value [-Wfloat-conversion]
result = sin (x);
^~~
所以我的问题是:是否有一个float 输入使用sin,就像上面一样,并且(隐式)将结果转换回float,将导致一个与使用获得的值不同的值sinf?
【问题讨论】:
-
135 / 180 * PI不会做你所期望的。请改用135.0 / 180 * PI -
对于
result = sin (x);MSVC 警告:从double转换为float,可能会丢失数据。 -
由于
sin和sinf的大多数实现都没有正确舍入,并且它们未正确舍入的方式不同,因此任何答案只能特定于一种实现(sin和 @ 987654347@). -
仅供参考,您发现的大多数不匹配可能是由于
sinf通常实现的精度接近float。例如,macOS 实现提供了如实四舍五入的结果——大多数结果都是正确四舍五入的(返回真实正弦的最接近的可表示值),但有些结果只是如实四舍五入(选择了两个周围的可表示值之一)。为此,正弦的计算误差小于float格式的 1 ULP,然后四舍五入为float... -
... 相比之下,
sin例程以更高的精度计算正弦,通常是double格式的几个 ULP。这意味着如果(float) sin(x)与sinf(x)不同,则前者通常是更好的结果。如果sin和sinf都返回正确的舍入结果,则(float) sin(x)和sinf(x)之间的差异将非常少见,仅发生在正弦导致双舍入错误的情况下(第一次舍入到double将其推过float舍入会改变的边界)。这是 2^29 中的一个。
标签: c floating-point precision trigonometry c99