Sujet : Re: Radians Or Degrees?
De : Keith.S.Thompson+u (at) *nospam* gmail.com (Keith Thompson)
Groupes : comp.lang.c comp.archDate : 17. Mar 2024, 03:57:17
Autres entêtes
Organisation : None to speak of
Message-ID : <87frwp36r6.fsf@nosuchdomain.example.com>
References : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
User-Agent : Gnus/5.13 (Gnus v5.13) Emacs/27.2 (gnu/linux)
bart <
bc@freeuk.com> writes:
On 17/03/2024 01:38, Keith Thompson wrote:
bart <bc@freeuk.com> writes:
On 16/03/2024 23:19, Keith Thompson wrote:
mitchalsup@aol.com (MitchAlsup1) writes:
>
Say you are a programmer and you receive a value like 2^53 from an
Input read and you wan the most accurate possible SIN( of that ).
I can't think of a scenario where that would be useful (other than
just
doing it for the sake of doing it).
If 2^53 represents a physical quantity, how likely is the actual
value
to be known within ±π (+/i pi for those who prefer ASCII)?
If you can get better precision without too much extra cost, that's
great. I don't know enough to have an opinion about what the best
tradeoff is, but I presume it's going to be different depending on the
application.
Here's a C program that shows how precise sin(2^53) can be for types
float, double, and long double (I used gcc and glibc). The nextafter
functions are used to compute the nearest representable number. For
long double, the value of sin() changes by about 1 part in 1600, which
seems decent, but it's not nearly as precise as for values around 1.0.
For float and double, the imprecision of the argument is enough to make
the result practically meaningless.
>
...
Output:
float (32 bits, 24 mantissa bits)
9007199254740992.00000000 -0.84892595
9007200328482816.00000000 -0.34159181
double (64 bits, 53 mantissa bits)
9007199254740992.00000000 -0.84892596
9007199254740994.00000000 -0.12729655
long double (128 bits, 64 mantissa bits)
9007199254740992.00000000 -0.84892596
9007199254740992.00097656 -0.84944168
>
Is this output supposed to be different between gcc -O0 and gcc -O3?
No, why do you ask?
On my system, the output is identical with gcc and clang, and tcc at
all
optimization levels, with both glibc and musl. I do get slightly
different results for long double on Cygwin vs. Ubuntu (Cygwin uses
newlib, not glibc).
>
>
Because I get the results shown below. Even if the library is
different from yours, I would have assumed matching results.
>
>
------------------------------
>
C:\c>gcc c.c -O3
>
C:\c>a
float (32 bits, 24 mantissa bits)
9007199254740992.00000000 -0.84892595
9007200328482816.00000000 -0.34159181
>
double (64 bits, 53 mantissa bits)
9007199254740992.00000000 -0.84892596
9007199254740994.00000000 -0.12729655
>
long double (128 bits, 64 mantissa bits)
9007199254740992.00000000 -0.84892596
9007199254740992.00097656 -0.84944168
>
C:\c>gcc c.c -O0
>
C:\c>a
float (32 bits, 24 mantissa bits)
9007199254740992.00000000 -0.84893209
9007200328482816.00000000 -0.34160271
>
double (64 bits, 53 mantissa bits)
9007199254740992.00000000 -0.84893209
9007199254740994.00000000 -0.12728505
>
long double (128 bits, 64 mantissa bits)
9007199254740992.00000000 -0.84893209
9007199254740992.00097656 -0.84944780
>
C:\c>gcc --version
gcc (tdm64-1) 10.3.0
I see similar results (possibly identical, I haven't checked) with
i686-w64-mingw32-gcc on Cygwin. I think it uses the same, or a similar,
runtime library as the tdm64 implementation you're using.
Comparing the generated assembly, at -O0 it generates a call to "sin",
while at -O1 and above it replaces the expression with a compile-time
constant. Apparently that compile-time constant matches the run-time
computed value for glibc, but not for whatever tdm64 uses.
I don't *think* it's a conformance issue as long as the precision is
within the standard's (fairly vague) requirements. When I modify the
program to start with sin(1.0) rather than sin(2**53), the output is
identical at all optimization levels.
Apparently glibc and the library used by tgm64 behave differently when
computing the sin of very large values. The result for sin(2**53) in
long double differs by about one part in 2**17 between -O0 and -O1, or
between gcc/glibc and tgm64.
-- Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.comWorking, but not speaking, for Medtronicvoid Void(void) { Void(); } /* The recursive call of the void */