First of all, "right" vs. "wrong" is a matter of language specification.
C# could be getting a different answer from Java, and yet produce an
acceptable answer within the terms of its language specification.

Similarly, Java only requires "The computed result must be within 1 ulp
of the exact result. Results must be semi-monotonic.". One could imagine
a language that requires the answer to be the round-to-nearest
equivalent of a value within one part in 1e100 of the infinitely precise
result. If a Java implementation did not get that answer, but did meet
the Java specification, would its answer be "wrong"?

During a calculation, any infinitely precise result in the range
[999999999999999.9375,1000000000000000.0625] gets rounded to the double
representation of 1e15. The width of that range, regarded as an angle,
is 0.125 radians, over seven degrees. The sine of the actual angle,
before rounding to double, could be anywhere between about 0.8245 and
about 0.8886.

A 64 bit floating point calculation that depends on taking sines of
angles around 1e15 radians is effectively operating with less than 2
decimal digit precision. It has far, far worse numerical problems than
the difference between the C# and Java results.

Of course, this does not address the question of whether there are any
angles for which Java's sine calculation is usefully more accurate than
C#'s. 1e15 is not one of them.

Advertisements

[Side-note: Hi Patricia! Good to be chatting again... it's been a long
time.]

Patricia Shanahan <> wrote:
> > It's not. I posted the evidence. C# gets wrong result.
>
> First of all, "right" vs. "wrong" is a matter of language specification.
> C# could be getting a different answer from Java, and yet produce an
> acceptable answer within the terms of its language specification.

In this case I don't think it's actually a language issue at all - it's
a standard libraries issue. C# and Java (the language) don't define any
trig methods as far as I'm aware. So long as the compiler can get the
value into the method accurately, and propagate the value back to the
caller accurately, the languages are doing their jobs.

There *are* interesting issues in terms of C# and its handling of
floating point numbers, because it doesn't guarantee that calculations
won't be performed at a higher precision than the type's
representation. Seehttp://msmvps.com/blogs/jon.skeet/archive/2005/10/02/68716.aspx
for an example of this.
> The next question is whether Java's answer is usefully better than C#'s
> answer. As Jon Harrop indicated earlier, 1e15 radians is too big for
> useful trig precision.

Agreed. One thing I find interesting is that Google's result is the
same as .NET's - if you type
sin(1e15)
into the search bar, you get 0.858272132, the same as the .NET answer.
That can't be pure coincidence, but I've no idea where the similarity
is...

In the same range, Math.sin varies (according to Java) between
0.42054779488070526 and 0.4205477915008597 - that's just by changing 2
ulps in the input. A significant change in the 9th DP, whereas C# was
wrong in the 14th DP at 1E7.

In other words, the error in the *output* of Math.Sin is almost
certainly going to be dwarfed by thee error in the *input* of Math.Sin
a that size of angle.

This is probably why .NET went the "quick" route - because no-one
realistically should be dealing with radian values that large in the
first place.

Jon Skeet [C# MVP] wrote:
> [Side-note: Hi Patricia! Good to be chatting again... it's been a long
> time.]

Hi Jon.
>
> Patricia Shanahan <> wrote:
>
>>>It's not. I posted the evidence. C# gets wrong result.
>>
>>First of all, "right" vs. "wrong" is a matter of language specification.
>>C# could be getting a different answer from Java, and yet produce an
>>acceptable answer within the terms of its language specification.
>
>
> In this case I don't think it's actually a language issue at all - it's
> a standard libraries issue. C# and Java (the language) don't define any
> trig methods as far as I'm aware. So long as the compiler can get the
> value into the method accurately, and propagate the value back to the
> caller accurately, the languages are doing their jobs.
....

Arguable in the case of Java. The Java Language Specification says that
each compilation unit implicitly starts with an import of "the
predefined package java.lang".

I don't know whether C# has any libraries with such a privileged position.

Jon Skeet [C# MVP] wrote:
> [Side-note: Hi Patricia! Good to be chatting again... it's been a long
> time.]
>
> Patricia Shanahan <> wrote:
>>> It's not. I posted the evidence. C# gets wrong result.
>> First of all, "right" vs. "wrong" is a matter of language specification.
>> C# could be getting a different answer from Java, and yet produce an
>> acceptable answer within the terms of its language specification.
>
> In this case I don't think it's actually a language issue at all - it's
> a standard libraries issue. C# and Java (the language) don't define any
> trig methods as far as I'm aware. So long as the compiler can get the
> value into the method accurately, and propagate the value back to the
> caller accurately, the languages are doing their jobs.
>

Unlike most previous languages Java is not really separable from its
standard library --- they come together, as do the mandated accuracy
requirements.

Patricia Shanahan <> wrote:
> > In this case I don't think it's actually a language issue at all - it's
> > a standard libraries issue. C# and Java (the language) don't define any
> > trig methods as far as I'm aware. So long as the compiler can get the
> > value into the method accurately, and propagate the value back to the
> > caller accurately, the languages are doing their jobs.
> ...
>
> Arguable in the case of Java. The Java Language Specification says that
> each compilation unit implicitly starts with an import of "the
> predefined package java.lang".

True - but it doesn't specify much about what's *in* that package, does
it? (I imagine it references java.lang.Exception, java.lang.Throwable
etc explicitly - but doesn't define java.lang.Math.sin.)
> I don't know whether C# has any libraries with such a privileged position.

Some types are referenced by the C# spec (System.Disposable, the
generic and nongeneric IEnumerable interfaces and a few others) but not
whole namespaces.

Mark Thornton <> wrote:
> > In this case I don't think it's actually a language issue at all - it's
> > a standard libraries issue. C# and Java (the language) don't define any
> > trig methods as far as I'm aware. So long as the compiler can get the
> > value into the method accurately, and propagate the value back to the
> > caller accurately, the languages are doing their jobs.
>
> Unlike most previous languages Java is not really separable from its
> standard library --- they come together, as do the mandated accuracy
> requirements.

Well, they come together to a *certain* extent - but they're not
inseparable. In particular you can easily use the Java platform without
using the Java language.

The VM spec is also separate from the language spec, which is a good
thing. It's just a shame that the name "Java" applies to the platform,
the runtime, and the language. With C# it's easier to communicate the
difference between talking about the language, the runtime, and the
libraries. (Which isn't to say everyone gets it right, of course...)

Razii <> wrote:
> >This is probably why .NET went the "quick" route - because no-one
> >realistically should be dealing with radian values that large in the
> >first place.
>
> We are discussing partialsums benchmark .

The post I was replying to wasn't - it was discussing sin(1e7)
and sin(1e10). This subthread was started with a post talking about
sin(1e15).

I still maintain that if you're using that magnitude of angle in a real
world application, you've got bigger problems. (In the benchmark,
giving a value of N=2500000 means you're still taking the sin of a
ridiculously large angle.)
> Let's change
>
> Console.WriteLine("{0:f9}\tFlint Hills", a4);
>
> to
>
> Console.WriteLine("{0:f16}\tFlint Hills", a4);
>
> and see if even get the same answer.

That's not the best way of finding out the exact value of a double. Seehttp://pobox.com/~skeet/csharp/floatingpoint.html and download
DoubleConverter.cs. Then you can use DoubleConverter.ToExactString to
find out the absolutely precise value.
> (.NET)
> 30.3145415095625000 Flint Hills
> 42.9952339980839000 Cookson Hills

I love the way you go straight from "most likely" to an absolute
assertion that the speed *is* at the cost of correctness. Note how the
benchmark doesn't provide "correct" values. Heck, the results posted
(in the languages I looked at, which was a fair variety) don't show
enough significant figures to show whether they agree with .NET, Java
or neither.

None of the languages is going to get a perfectly accurate answer, of
course - the accumulated error over 2.5 million additions is likely to
be pretty significant, especially when each of the values added is only
an approximation to the mathematical truth anyway.

Now when a platform starts giving inappropriate answers on *sensible*
questions, that's when I'd get more worried.

Jon Skeet [C# MVP] wrote:
> Mark Thornton <> wrote:
>>> In this case I don't think it's actually a language issue at all - it's
>>> a standard libraries issue. C# and Java (the language) don't define any
>>> trig methods as far as I'm aware. So long as the compiler can get the
>>> value into the method accurately, and propagate the value back to the
>>> caller accurately, the languages are doing their jobs.
>> Unlike most previous languages Java is not really separable from its
>> standard library --- they come together, as do the mandated accuracy
>> requirements.
>
> Well, they come together to a *certain* extent - but they're not
> inseparable. In particular you can easily use the Java platform without
> using the Java language.
>
> The VM spec is also separate from the language spec, which is a good
> thing. It's just a shame that the name "Java" applies to the platform,
> the runtime, and the language.
And at times several other things with no obvious relationship at the
whim of Sun's marketing department. I seem to recall that the meaning of
..NET has had a few iterations as well.

Mark Thornton <> wrote:
> > The VM spec is also separate from the language spec, which is a good
> > thing. It's just a shame that the name "Java" applies to the platform,
> > the runtime, and the language.
> And at times several other things with no obvious relationship at the
> whim of Sun's marketing department. I seem to recall that the meaning of
> .NET has had a few iterations as well.

Oh yes indeed It's now mostly stabilised - although *exactly* what
LINQ means has taken over as the "less well defined" term in my view

Razii wrote:
> > I love the way you go straight from "most likely" to an absolute
> > assertion that the speed is at the cost of correctness.
>
> That's pretty good assumption given that C# gets the wrong answer for
> 1e7, 1e10, 1e15

Anything using input values like that for sines is bound to get
inaccurate answers. Anyone understanding a bit about floating point
values knows that it is simply foolish to try to find the sine of such
values and still expect any accuracy.

I also wonder why one would want to do this. It doesn't make any sense.
--
Rudy Velthuis http://rvelthuis.de

"A fast word about oral contraception. I asked a girl to go to
bed with me, she said 'no'." -- Woody Allen

Your "right answer" is more precise, but, due to the nature of decimal
representations of real values, it is still off a little. Expecting
more accuracy than the .NET program gives with a "double precision"
floating point value is quite foolish.

I'm sure there are libraries that will calculate the sine of 1e10 up to
1000 decimals, but except specialized math languages, I doubt there are
computer langusges where it makes sense to go that far. <g>
--
Rudy Velthuis http://rvelthuis.de

Rudy Velthuis wrote:
> Razii wrote:
>
>>> I love the way you go straight from "most likely" to an absolute
>>> assertion that the speed is at the cost of correctness.
>> That's pretty good assumption given that C# gets the wrong answer for
>> 1e7, 1e10, 1e15
>
> Anything using input values like that for sines is bound to get
> inaccurate answers. Anyone understanding a bit about floating point
> values knows that it is simply foolish to try to find the sine of such
> values and still expect any accuracy.
>
> I also wonder why one would want to do this. It doesn't make any sense.

While I agree that it is unlikely to have any application in physics or
engineering, sometimes mathematicians do find good reasons for computing
apparently unlikely values. After all there was once a time when
computations on 500+ bit integers would have been considered of no
practical use. Now our security depends on such work.

Before Java, the accuracy of many trig libraries was rather
underspecified. Java's specification may be too strict, but at least it
has one.

Mark Thornton <> wrote:
> > I also wonder why one would want to do this. It doesn't make any sense.
>
> While I agree that it is unlikely to have any application in physics or
> engineering, sometimes mathematicians do find good reasons for computing
> apparently unlikely values. After all there was once a time when
> computations on 500+ bit integers would have been considered of no
> practical use. Now our security depends on such work.

True. I think there's a significant difference between integer
arithmetic and floating point - but I agree it's hard to predict the
future.
> Before Java, the accuracy of many trig libraries was rather
> underspecified. Java's specification may be too strict, but at least it
> has one.

Oh indeed. The fact that there's both Math and StrictMath is
particularly nice. It would be interesting to see a port of StrictMath
for .NET.

Razii <> wrote:
> >> This is probably why .NET went the "quick" route - because no-one
> >> realistically should be dealing with radian values that large in the
> >> first place.
> >
> >Indeed.
>
> Skeet is wrong. It's not just limited to large values. C# just uses
> the hardware fsin/fcos values. The value of sine for the
> floating-point number Math.PI is around
>
> 1.2246467991473532E-16
> 1.22460635382238E-16 (C# -- same answer as returned by fsin)
>
> Are you telling us that C# is a bad choice for software that must be
> platform independent? On different hardware the answer would be
> different if you are using C#.

If you need bit-for-bit reproducability for all calculations, then I
certainly agree that C# is unsuitable. Aside from the Math library
calls, the CLI spec allows for a runtime to use higher precision for
arithmetic where it wishes to. See section 12.1.3 of ECMA-335 for more
information and a rationale.

Mark Thornton wrote:
> > I also wonder why one would want to do this. It doesn't make any
> > sense.
>
> While I agree that it is unlikely to have any application in physics
> or engineering, sometimes mathematicians do find good reasons for
> computing apparently unlikely values.

No doubt. But any mathematician knowing anything how floating point
numbers are implemented would think twice before doing that using
"double precision", i.e. 8 byte floating point values.

Razii wrote:
> Skeet is wrong. It's not just limited to large values. C# just uses
> the hardware fsin/fcos values. The value of sine for the
> floating-point number Math.PI is around
>
> 1.2246467991473532E-16
> 1.22460635382238E-16 (C# -- same answer as returned by fsin)
>
> Are you telling us that C# is a bad choice for software that must be
> platform independent?

I am telling that the combination of double precision (8 byte, with 52
bits for the mantissa) floating point values with such large values is
simply a bad one.

Of course .NET uses the hardware FPU on an x86 or x64 system.

Since the error you see for Pi is ~1e-16, which is in 52nd bit of the
mantissa (before normalization), that is excellent. Since for values
close to 0 one can say that sin(x) = x, this means the error is as
small as can be, using a mantissa of 52 bits. IOW, a more accurate
result is impossible with a mantissa of 52 bits.

If you want higher precision, don't use the builtin routines. These
were not designed for that, just like the builtin math routines for
most languages I know. I'm sure C, C++, Delphi etc. would give you
similar results, on an x86.

Razii wrote:
> On Wed, 04 Jun 2008 15:56:46 -0700, "Rudy Velthuis"
> <> wrote:
>
> > If you want higher precision, don't use the builtin routines.
>
> That was not the point. The point was that you get different answers
> on different hardware. So the speed in this case comes at the cost
> that software may behave differently on different hardware.

That is the cost of using the available FPU, indeed. The alternative is
using a library that does everything in code. Not feasible for many
applications, I'd guess. Note that C and C++ also use the available
hardware.
--
Rudy Velthuis http://rvelthuis.de

<snip>
> So we are done with this partialsums benchmark; this was the only case
> where C# was significantly faster.

And I for one have never been claiming that .NET or C# is significantly
faster than Java overall. (If any benchmarks made custom calls to
native code, that would be interesting. I really have no idea how JNI
compares with P/Invoke in terms of speed. I know which is more pleasant
to use, mind you

Given how similar their overall approach is, and how both of them have
had a lot of time and money spent optimising their VMs (with more work
to be done, for sure) it's unsurprising that they're pretty much a tie.

My conclusion: don't choose between Java and .NET on performance
grounds. There are far better reasons to choose one or the other,
depending on other criteria.

Share This Page

Welcome to The Coding Forums!

Welcome to the Coding Forums, the place to chat about anything related to programming and coding languages.

Please join our friendly community by clicking the button below - it only takes a few seconds and is totally free. You'll be able to ask questions about coding or chat with the community and help others.
Sign up now!