<p>The real answer here is another question:  why do you think you need this?  There may be a better way to accomplish what you're trying to do that doesn't depend on intricate details of platform floating-point.  Having said that...</p>

<p>It's unfortunate that you can't change the Linux code, since it's really the Linux results that are deficient here.  The SUN results are as good as they could possibly be:  they're correctly rounded; each multiplication gives the unique (in this case) C double that's closest to the result.  In contrast, the first Linux multiplication does <em>not</em> give a correctly rounded result.</p>

<p>Your Linux results come from a 32-bit system on x86 hardware, right?  The results you show are consistent with, and likely caused by, the phenomenon of 'double rounding': the result of the first multiplication is first rounded to 64-bit precision (the precision used internally by the Intel x87 FPU), and then re-rounded to the usual 53-bit precision of a double.  Most of the time (around 1999 times out of 2000 or so on average) this double round has the same effect as a single round to 53-bit precision would have had, but occasionally it can produce a different result, and that's what you're seeing here.</p>

<p>As you say, there are ways to fix the Linux results to match the Solaris ones:  one of these is to use appropriate compiler flags to force the use of SSE2 instructions for floating-point operations if possible.  The recent 4.5 release of gcc also fixes the difference by means of a new <a href="http://gcc.gnu.org/onlinedocs/gcc-4.5.0/gcc/Optimize-Options.html#index-fexcess_002dprecision-809" rel="nofollow noreferrer"><code>-fexcess-precision</code></a> flag, though the fix may impact performance when not using SSE2.</p>

<p>[Edit:  after several rereads of the gcc manuals, the gcc-patches mailing list thread at <a href="http://gcc.gnu.org/ml/gcc-patches/2008-11/msg00105.html" rel="nofollow noreferrer">http://gcc.gnu.org/ml/gcc-patches/2008-11/msg00105.html</a>, and the related <a href="http://gcc.gnu.org/bugzilla/show_bug.cgi?id=323" rel="nofollow noreferrer">gcc bug report</a>, it's still not clear to me whether use of <code>-fexcess-precision=standard</code> does in fact eliminate double rounding on x87 systems;  I think the answer depends on the value of FLT_EVAL_METHOD.  I don't have a 32-bit Linux/x86 machine handy to test this on.]</p>

<p>But I don't know how you'd fix the Solaris results to match the Linux ones, and I'm not sure why you'd want to:  you'd be making the Solaris results less accurate instead of making the Linux results more accurate.</p>

<p>[Edit:  caf has a good suggestion here.  On Solaris, try deliberately using long double for intermediate results, then forcing back to double.  If done right, this should reproduce the double rounding effect that you're seeing in Linux.]</p>

<p>See David Monniaux's excellent paper <a href="http://arxiv.org/abs/cs/0701192" rel="nofollow noreferrer">The pitfalls of verifying floating-point computations</a> for a good explanation of double rounding.  It's essential reading after the Goldberg article mentioned in an earlier answer.</p>
How to make gcc on SUN calculate floating points the same way as in Linux
<p>I have a project where I have to perform some mathematics calculations with double variables.
The problem is that I get different results on SUN Solaris 9 and Linux.
There are a lot of ways (explained here and other forums) how to make Linux work as Sun, but not the other way around.
I cannot touch the Linux code, so it is only SUN I can change.
Is there any way to make SUN to behave as Linux?</p>

<p>The code I run(compile with gcc on both systems):</p>

<pre><code>int hash_func(char *long_id)          
{                                 
    double      product, lnum, gold;
    while (*long_id)
        lnum = lnum * 10.0 + (*long_id++ - '0');
    printf("lnum  =&gt; %20.20f\n", lnum);
    lnum = lnum * 10.0E-8;
    printf("lnum  =&gt; %20.20f\n", lnum);
    gold = 0.6125423371582974;
    product = lnum * gold;
    printf("product =&gt; %20.20f\n", product);
    ...
}
</code></pre>

<p>if the input is 339886769243483</p>

<p>the output in Linux:</p>

<pre><code>lnum  =&gt; 339886769243**483**.00000000000000000000

lnum  =&gt; 33988676.9243**4829473495483398**

product =&gt; 20819503.600158**59827399253845**
</code></pre>

<p>When on SUN:</p>

<pre><code>lnum =&gt; 339886769243483.00000000000000000000

lnum =&gt; 33988676.92434830218553543091

product = 20819503.600158**60199928283691**
</code></pre>

<p><em>Note:</em> The result is not always different, moreover most of the times it is the same. Just 10  15-digit numbers out of 60000 have this problem.</p>

<p>Please help!!!</p>