On Tuesday, May 8, 2018 at 5:53:43 AM UTC-4,
bol...@cylonhq.com wrote:
> On Tue, 08 May 2018 16:59:14 +0800
> Reinhardt Behm <
rb...@hushmail.com> wrote:
> >AT Tuesday 08 May 2018 16:51, bol...@cylonHQ.com wrote:
> >
> >> On Mon, 07 May 2018 12:38:13 -0500
> >> Robert Wessel <
robert...@yahoo.com> wrote:
> >>>On Mon, 7 May 2018 08:31:31 +0000 (UTC), bol...@cylonHQ.com wrote:
> >>>>>return h / std::sqrt(e * voltage * m * (e * voltage / (m * c*c) + 2.0));
> >>>>
> >>>>And the result of that would be accurate would it? I hope its not code
> >>>>for any safety related control system.
> >>>
> >>>
> >>>Why wouldn't it be? Assuming a suitable range of values for voltage
> >>>(within a few orders of magnitude of 10**-4), the various constants
> >>>being correct, and the formula being correct. Performing
> >>>multiplicative* operations on FP numbers of wildly differing
> >>>magnitudes does not lose accuracy. Additive operations *do*, which is
> >>>where the range limit mentioned for voltage comes from.
> >>
> >> Safety systems like exact values, not "within a reasonable distance of
> >> what we want" values. Get the flaps angle on an aircraft a fraction of a
> >> degree out and you could find yourself in a stall or a dive PDQ. But hey,
> >> its close enough, right?
> >
> >You really expect an physical quantities to be exact to 10^-7?
>
> No, but inaccuracies with floating point calcs soon add up.
Do they? Let's see.
I haven't had any practical use of my knowledge of elementary particle
physics since I was a research assistant in grad school, but I can look
at that formula and realize that if it's related to acceleration of an
electron across a voltage drop. If that experience had been only two
decades more recent, I probably would even recognize that formula. Since
I don't, I'm not sure what range of values are reasonable for voltage,
and my knowledge of experimental physics was never sufficiently practical
for me to be sure with what accuracy such voltages could be measured.
Simple analysis indicates that any value for voltage between -2*m*c*c/e
and 0.0 would cause a domain error for std::sqrt(). The heaviest
elementary particle known so far is only about 172GeV, so I used an
upper limit of 1 TV. To give your thesis it's best opportunity to be
valid, I'll assume that the voltage is measured so accurately that
double precision floating point limits the accuracy with which it can be
represented - which is absurd - that would make it one of the most
accurately measured physical quantities ever known.
#include <cmath>
#include <iomanip>
#include <iostream>
#include <limits>
// <
https://physics.nist.gov/cuu/Constants/index.html>
const double h = 6.626070040e-34;
const double hp = std::nextafter(h,1);
const double hm = std::nextafter(h,0);
const double hmin = h - 0.000000081e-34;
const double hmax = h + 0.000000081e-34;
const double e = 1.6021766208e-19;
const double ep = std::nextafter(e,1);
const double em = std::nextafter(e,0);
const double emin = e-0.0000000098e-19;
const double emax = e+0.0000000098e-19;
const double m = 9.10938356e-31;
const double mp = std::nextafter(m,1);
const double mm = std::nextafter(m,0);
const double mmin = m - 0.00000011e-31;
const double mmax = m + 0.00000011e-31;
// Note that none of the physical constants listed above even comes close
// to being limited by the use of double precision floating point.
// The modern metric system defines this value of c to be exact:
const double c = 2.99792458e8;
const double cp = std::nextafter(m,1);
const double cm = std::nextafter(m,0);
const double twom = nextafter(2.0, 1.0);
const double twop = nextafter(2.0, 3.0);
void func(double voltage)
{
const double vp = nextafter(voltage, std::numeric_limits<double>::max());
const double vm = nextafter(voltage, -std::numeric_limits<double>::max());
const double vs = voltage > 0 ? vm : vp;
const double vl = voltage > 0 ? vp : vm;
const double result = h/std::sqrt(e*voltage*m*(e*voltage/(m*c*c)+2.0));
const double low_physical =
hmin/std::sqrt(emax*vl*mmax*(emax*vl/(mmin*c*c)+2.0));
const double high_physical =
hmax/std::sqrt(emin*vs*mmin*(emin*vs/(mmax*c*c)+2.0));
const double low_fp =
hm/std::sqrt(ep*vl*mp*(ep*vl/(mm*cm*cm)+twop));
const double high_fp =
hp/std::sqrt(em*vs*mm*(em*vs/(mp*cp*cp)+twom));
std::cout << std::setw(11) << voltage << "\t" << result << "\t"
<< high_physical-low_physical << "\t" << high_fp-low_fp << "\n";
}
int main(void)
{
const double vcrit = 2.0*m*c*c/e;
const double vmax = 1e15;
std::cout << "Voltage\t\tResult\t\tPhysical\tFP\n" << std::setw(11);
for(double voltage = std::numeric_limits<double>::epsilon()*vcrit;
voltage < vmax; voltage *= 2.0)
func(voltage);
for(double voltage = -vcrit; voltage > -vmax; voltage *= 2.0)
func(voltage);
return 0;
}
Do you see any cases where the floating point round-off error even comes
close to the error due to the uncertainties in the values of the
physical constants?
Would you care to demonstrate how you could use a fixed point type with
only 64 bits before and after the decimal point to perform such
calculations with accuracy limited more by the accuracy of the physical
constants than by the very limited precision of that format?