473,802 Members | 1,984 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

sqrt Behaving Unexpectedly --- Short Program Example

The bits get twiddled every now and then.
Using gcc 3.2 and 3.4.

To build: cc -o test test.c -lm

---------------- 8< test.c ------------------------
#include <stdio.h>
#include <math.h>

double func(double);

int main() {

int ii ;
double x, r1, r2 ;

x = 2510771730459.3 74023 ;

for ( ii = 0 ; ii < 100 ; ii++ ) {

r1 = sqrt( 3*x*x ) ;
r2 = sqrt(func(3*x)* x);

if ( r1 != r2 ) {
fprintf(stderr, "\nIteration=%d \n", ii);
fprintf(stderr, "val1=%#llx \n",
*(unsigned long long*)(&r1)) ;
fprintf(stderr, "val2=%#llx \n",
*(unsigned long long*)(&r2)) ;
}
x = r1 ;
}

return 0 ;
}

double func( double temp ) {
return(temp);
}
--------------------------------------------------------------
Thanks for any reasons why this occurs.

Keith

Nov 14 '05 #1
9 1758
Simpler program that shows the same thing:

-----------------8<-------------------------
#include <stdio.h>
#include <math.h>

int main() {

int ii ;
double x, y, r1, r2 ;

x = 2510771730459.3 74023 ;

for ( ii = 0 ; ii < 100 ; ii++ ) {

r1 = sqrt( 3*x*x ) ;
y = 3*x ;
r2 = sqrt(x*y);

if ( r1 != r2 ) {
fprintf(stderr, "\nIteration=%d \n", ii);
fprintf(stderr, "val1=%#llx \n",
*(unsigned long long*)(&r1)) ;
fprintf(stderr, "val2=%#llx \n",
*(unsigned long long*)(&r2)) ;
fprintf(stderr, "r=%lf\n", 3*r2);
}
x = r1 ;
}

return 0 ;
}
----------------------------------------------------

Nov 14 '05 #2


Keith wrote:
The bits get twiddled every now and then.
Using gcc 3.2 and 3.4.
[code snipped; see up-thread]


Part of what you're seeing is covered by Questions 14.1
and 14.4 of the comp.lang.c Frequently Asked Questions (FAQ)
list

http://www.eskimo.com/~scs/C-faq/top.html

In floating-point arithmetic, expressions that are
"algebraica lly identical" can sometimes yield computationally
different results. The whys and wherefores stray into the
particular characteristics of different C implementations ,
which aren't really topical here. Suffice it to say that
on some implementations , in

double x, y, z;
x = ...;
y = 3 * x * x;
z = 3 * x;
z = z * x;

.... `y' and `z' will not have exactly the same value. On
other machines, they will: I ran your code on two different
machines and got equality on one, "twiddled bits" on the
other. Be comforted (and read Question 14.4 again): the
difference between `y' and `z', while not necessarily zero,
will be very small[*].
[*] "Very small" for these expressions, but not for all.
For example, try

double x = 1.0, y = 1.0e30;
printf ("%g\n%g\n", (x + y) - y, x + (y - y));

If you want to learn more about such effects, why they arise,
and how to avoid being bitten by them, read the first few
chapters of any textbook with the phrase "Numerical Analysis"
in the title.

--
Er*********@sun .com

Nov 14 '05 #3
Thanks Eric. I wrote this to the person that asked me the question
initially about a change in simulation response. I do not know what
group to pose gcc differences to.

I think that the key is where Eric said,
In floating-point arithmetic, expressions that are
"algebraica lly identical" can sometimes yield computationally
different results. The whys and wherefores stray into the
particular characteristics of different C implementations ...
I suppose that is to say that gcc 3.2 and 3.4 (two different C
implementations ) did something different which changed something
considered to be fundamental.

The change is "small[*]" as he put it, but neverthless makes
significant differences. It is especially significant when comparing
against a validated simulation response! Especially when a pointy head
is staring at you with an eyebrow raised.

I don't really know how to accept the changes that are imposed on us by
things we don't control. It is unsettling that a compiler upgrade
changes the angle of an end effector by a 10th of a degree or whatever.
What are you going to do?

Hmmm. I suppose you have to ask what is truth. Seems like things aren't
so black and white. How was the first response "vailidated "? How did it
become "accepted"?

Seems like the weather to me. Butterfly wings causing weather changes.

If I was the ruler of the world I might suggest that when considering
simulation responses and issues of bit twiddling changing responses,
that modelers should keep the response within an epsilon. After all, it
is simulation.

If the validated response IS reality, and NO deviation can occur then
we are all in a heap of trouble. RK2 or RK4 or the best stinking
look-ahead-multi-parallel-heuristic-stochastic integrator in the
universe will fail. We'll have to scramble for f(t) which describes the
station and shuttle in time. And we'll have no need for Trick. We just
need f(t). And I won't have a job.

It is chaos. The nature of things.
Yep. Too much green tea this morning.

Keith

Nov 14 '05 #4


Keith wrote:
Thanks Eric. I wrote this to the person that asked me the question
initially about a change in simulation response. I do not know what
group to pose gcc differences to.

I think that the key is where Eric said,
In floating-point arithmetic, expressions that are
"algebraica lly identical" can sometimes yield computationally
different results. The whys and wherefores stray into the
particular characteristics of different C implementations ...

I suppose that is to say that gcc 3.2 and 3.4 (two different C
implementations ) did something different which changed something
considered to be fundamental.
What's *probably* going on is that the two compilers
generate different code sequences for the floating-point
calculations. Some machines use more precision for F-P
values in their internal registers than when those values
are stored back into memory; x86 designs, for example, use
80-bit F-P while calculating but round the result to 64
bits when storing it back to a `double' variable. Hence
the compiler's decisions about which intermediate results
to hold in registers and which to round and store back to
memory can affect the outcome of the computation. Change
the compiler version, change the optimization level, write
expressions in different although "algebraica lly equivalent"
ways, and you'll get different decisions from the compiler.
The change is "small[*]" as he put it, but neverthless makes
significant differences. It is especially significant when comparing
against a validated simulation response! Especially when a pointy head
is staring at you with an eyebrow raised.
The "small" effect I observed (on an x86 machine, as it
happens) amounted to a change in the least significant bit
of the result. If a relative error of fifty-five billionths
of a billionth (55.5e-18) raises eyebrows, the heads those
eyebrows decorate must come to very sharp points indeed.
Hmmm. I suppose you have to ask what is truth. Seems like things aren't
so black and white. How was the first response "vailidated "? How did it
become "accepted"?


"That is the question." -- Hamlet, Prince of Denmark

--
Er*********@sun .com
Nov 14 '05 #5
On Wed, 02 Feb 2005 08:05:30 -0800, Keith wrote:

....
I suppose that is to say that gcc 3.2 and 3.4 (two different C
implementations ) did something different which changed something
considered to be fundamental.

The change is "small[*]" as he put it, but neverthless makes
significant differences.
If the differences are significant enough to be a problem then the code is
probably faulty to start with. Perhaps data is not being held to a high
enough precision for the purpose, or algorithms and formulae are being
used that have bad behaviour in this respect.
It is especially significant when comparing
against a validated simulation response! Especially when a pointy head
is staring at you with an eyebrow raised.
Where floating point is concerned a validated result should be specified
within error bounds. If your new result is within those bounds there is no
problem, if it isn't then the program is probably buggy.
I don't really know how to accept the changes that are imposed on us by
things we don't control. It is unsettling that a compiler upgrade
changes the angle of an end effector by a 10th of a degree or whatever.
What are you going to do?

Hmmm. I suppose you have to ask what is truth. Seems like things aren't
so black and white. How was the first response "vailidated "? How did it
become "accepted"?
Right. Is there any reason to believe that the original result is "better"
than the new one?
Seems like the weather to me. Butterfly wings causing weather changes.
Don't believe this myself, a butterfly wingbeat will cause the position
of individual molecules in the air to be increasingly different as time
goes on, an effect which will propagate around the world, but the
difference in macroscopic effects such as those responsible for weather
are likely to decrease. OTOH errors almost invariably increase as you
progress through a calculation.
If I was the ruler of the world I might suggest that when considering
simulation responses and issues of bit twiddling changing responses,
that modelers should keep the response within an epsilon. After all, it
is simulation.


Error analysis need to be performed, yes. Without that there's no
guarantee that the results have any meaning at all.

....

Lawrence
Nov 14 '05 #6
Eric wrote:
If a relative error of fifty-five billionths
of a billionth (55.5e-18) raises eyebrows, the heads those
eyebrows decorate must come to very sharp points indeed.


To defend the pointy heads, which I am not likely to do very often, the
billionths wouldn't raise the eyebrow of the most pointiest of pointy
heads. The problem is that over time the algorithms slowly begin to
change the outcome to a semi-significant level. At this
semi-significant level, the pointy head's eyebrow rises. Defending the
pointy head again, the response is important and may deserve attention.
The answer to the pointy heads is more philosophic when it comes to
what you consider to be a "truth model" when using imprecise algorithms
and imprecise machinery. I have already posted my thoughts over the
nature of what is "right" so no need to say that the discrete nature of
how computers represent real numbers make programs imprecise.

The beginning issue was whether the precision should change from C
compiler to C compiler with such a seemingly innocuous issue as the
3*x*x deal. You've answered that question when you said that execution
is compiler implementation dependent. So that helps a lot. The
details you gave about what is *probably* going on between the
compilers help too. Thanks.

Nov 14 '05 #7
Lawrence wrote:
Error analysis need to be performed, yes. Without that there's no
guarantee that the results have any meaning at all. Yep. That sums it up.

Lawrence wrote:
Seems like the weather to me. Butterfly wings causing weather

changes.
Don't believe this myself, a butterfly wingbeat
will cause the position
of individual molecules in the air to be increasingly
different as time goes on, an effect which will propagate
around the world, but thedifference in macroscopic effects
such as those responsible for weather are likely to decrease.
OTOH errors almost invariably increase as you
progress through a calculation.


That chaos example of a butterfly seems far fetched, huh?
I have seen the error increase with "higher fidelity" algorithms just
because of calculation induced error.

The fact that the x86 uses 80 bit registers *could* explain why there
are differences between a function call and a macro. The function call
would lose precision since the double passed would be reduced to fit on
the function stack.

Nov 14 '05 #8
Keith wrote:
The bits get twiddled every now and then.
Using gcc 3.2 and 3.4.

To build: cc -o test test.c -lm

---------------- 8< test.c ------------------------
#include <stdio.h>
#include <math.h>

double func(double);

int main() {

int ii ;
double x, r1, r2 ;

x = 2510771730459.3 74023 ;

for ( ii = 0 ; ii < 100 ; ii++ ) {

r1 = sqrt( 3*x*x ) ;
r2 = sqrt(func(3*x)* x);

if ( r1 != r2 ) {
fprintf(stderr, "\nIteration=%d \n", ii);
fprintf(stderr, "val1=%#llx \n",
*(unsigned long long*)(&r1)) ;
fprintf(stderr, "val2=%#llx \n",
*(unsigned long long*)(&r2)) ;
}
x = r1 ;
}

return 0 ;
}

double func( double temp ) {
return(temp);
}
--------------------------------------------------------------
Thanks for any reasons why this occurs.

Keith


Double has approx 15 significant digits in the IEEE floating point standard,
used by all modern computers. You will get problems like this as the
calculations differ in one or two bits.

Instead compare the absolute value of the difference.

gtoomey
Nov 14 '05 #9
On Wed, 02 Feb 2005 12:18:17 -0800, Keith wrote:
Lawrence wrote:
Error analysis need to be performed, yes. Without that there's no
guarantee that the results have any meaning at all. Yep. That sums it up.

Lawrence wrote:
Seems like the weather to me. Butterfly wings causing weather

changes.
Don't believe this myself, a butterfly wingbeat
will cause the position
of individual molecules in the air to be increasingly
different as time goes on, an effect which will propagate
around the world, but thedifference in macroscopic effects
such as those responsible for weather are likely to decrease.
OTOH errors almost invariably increase as you
progress through a calculation.


That chaos example of a butterfly seems far fetched, huh?


Just a misapplication of the principles of Chaos Theory. A little
knowledge is often far more dangerous than no knowledge.
I have seen the error increase with "higher fidelity" algorithms just
because of calculation induced error.
That's why error analysis is so important. A result is meaningless unless
you know what the error bounds are.
The fact that the x86 uses 80 bit registers *could* explain why there
are differences between a function call and a macro. The function call
would lose precision since the double passed would be reduced to fit on
the function stack.


In the error analysis you would assume the lowest possible precision at
all steps. If the precision happens to be higher it's not a problem,
except in the case of some specific algorithms that require a consistent
precision to work.

Lawrence
Nov 14 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

10
7328
by: pauldepstein | last post by:
I am writing a program which will use the ceiling and floor of square roots. If a positive integer is an exact square (and is not overly huge), does sqrt return an integer-valued real? Or might the sqrt function tell me that, for example, sqrt(1024) = 31.99999999999999999999999 You might say "try it". The problem is that I can't try infinitely
7
6771
by: Aric | last post by:
Hi, I'm a bit new to programming in general, really I've just picked it up as a hobby, and so I've started by reading "Practical C Programming" by Steve Oualline. Things have been going fine in the book until I reached exercise 6-1 in the book, which reads: Write a program to find the square of the distance between two points. (For a more advanced problem, find the actual distance. This problem involves using the standard function...
2
19480
by: Matt Sollars | last post by:
Hi all. I'm having a nasty problem. A client's website was originally written with classic ASP. They requested a new portion of the site that was deemed a perfect candidate for ASP.NET. So, .NET was installed on their web server and one of the subdirectories in the web site was converted to a virtual application to support the new pages that would be added. The rest of the site was left untouched. New aspx files were added to this...
7
6717
by: Ralf Gedrat | last post by:
Hello! I have some Vb.Net applications, which are terminated at indefinite times without message. If I call in the program regulated system.GC.Collect, then the program is terminated here sporadically without message. It's not possible to debug in visual studio, i get no exceptions (application is terminated unexpectedly without message).
13
3778
by: Michael McNeil Forbes | last post by:
I would like to write a module that provides some mathematical functions on top of those defined in math, cmath etc. but I would like to make it work with "any" type that overloads the math functions. Thus, I would like to write: module_f.py ---- def f(x): """ Compute sqrt of x """
14
4774
by: peng.xiaoyu | last post by:
hello everyone, why this c code can be compiled and linked without -lm? #include<math.h> #include<stdio.h> int main() { printf("%f\n",sqrt(2.0)); return 0;
30
4048
by: copx | last post by:
I am writing a program which uses sqrt() a lot. A historically very slow function but I read on CPUs with SSE support this is actually fast. Problem: C's sqrt() (unlike C++ sqrt()) is defined to work on doubles only, and early versions of SSE did not support double precision. The CPU requirement "something with at least first generation SEE support" (everything from P3/Athlon XP and up) is acceptable for me. However, requiring a CPU which...
13
10556
by: =?Utf-8?B?RXRoYW4gU3RyYXVzcw==?= | last post by:
Hi, Why does Math.Sqrt() only accept a double as a parameter? I would think it would be just as happy with a decimal (or int, or float, or ....). I can easily convert back and forth, but I am interested in what is going on behind the scenes and if there is some aspect of decimals that keep them from being used in this calculation. Thanks! Ethan Ethan Strauss Ph.D.
3
10516
by: Johnson | last post by:
I'm not sure if this is an IIS 5.1 issue or ASP.NET issue, or Visual Studio 2008 issue -- thus posting to 3 groups. Please don't be offended. The problem I'm encountering is that Visual Studio closes unexpectedly and without any error message being displayed, or error messages written to the system logs. Visual Studio closes when I attempt to open an ASP.NET Web application (not Web site) solution for which IIS is set as the project's...
0
9699
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9562
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10538
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10305
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
10285
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
1
7598
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5622
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4270
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
3792
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.