Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Clean Singleton Docstrings

275 views
Skip to first unread message

Rob Gaddi

unread,
Jul 7, 2016, 7:46:59 PM7/7/16
to
I've got a package that contains a global ensmartened dict that allows
all the various parts of my program to share state. Things like device
handles, information about the application environment, etc. that are
inherantly global (i.e. we're not having that debate).

Implementation is:

class _Registry(UserDict):
"""Docstring!"""
...
Registry = _Registry()

So Registry is now a globally accessible mutable object; no reason to
complicate things with singletons or borgs or whathave you. From
within the interactive console, help(foobar.Registry) gives me the
_Registry documentation as expected.

From the (Linux) command line though:
$ pydoc3 foobar._Registry
[lots of good documentation stuff]
$ pydoc3 foobar.Registry
no Python documentation found for 'foobar.Registry'

Is this a thing that can be fixed with a commensurate amount of effort?

Thanks,
Rob

--
Rob Gaddi, Highland Technology -- www.highlandtechnology.com

Email address domain is currently out of order. See above to fix.

Steven D'Aprano

unread,
Jul 7, 2016, 10:53:55 PM7/7/16
to
On Fri, 8 Jul 2016 09:46 am, Rob Gaddi wrote:
[...]

> So Registry is now a globally accessible mutable object; no reason to
> complicate things with singletons or borgs or whathave you. From
> within the interactive console, help(foobar.Registry) gives me the
> _Registry documentation as expected.
>
> From the (Linux) command line though:
> $ pydoc3 foobar._Registry
> [lots of good documentation stuff]
> $ pydoc3 foobar.Registry
> no Python documentation found for 'foobar.Registry'
>
> Is this a thing that can be fixed with a commensurate amount of effort?

[steve@ando ~]$ python3 -m pydoc --help
pydoc - the Python documentation tool

pydoc <name> ...
Show text documentation on something. <name> may be the name of a
Python keyword, topic, function, module, or package, or a dotted
reference to A CLASS OR FUNCTION within a module [...]

(Emphasis added.)


So, no, reading the docstrings from individual objects is not supported by
pydoc's command line interface. You could possibly add that functionality,
but I don't know how much effort it would be.




--
Steven
“Cheer up,” they said, “things could be worse.” So I cheered up, and sure
enough, things got worse.

Michael Selik

unread,
Jul 7, 2016, 11:43:43 PM7/7/16
to


> On Jul 7, 2016, at 7:46 PM, Rob Gaddi <rga...@highlandtechnology.invalid> wrote:
>
> I've got a package that contains a global ensmartened dict that allows
> all the various parts of my program to share state.

The simplest solution would be to use a module as your singleton. For example, "registry.py" would work. Pydoc will show its docstring, and it will have all the features you had been using, with the added benefit of not needing to enforce its singletonness.

Peter Otten

unread,
Jul 8, 2016, 3:38:56 AM7/8/16
to
Rob Gaddi wrote:

> I've got a package that contains a global ensmartened dict that allows
> all the various parts of my program to share state. Things like device
> handles, information about the application environment, etc. that are
> inherantly global (i.e. we're not having that debate).
>
> Implementation is:
>
> class _Registry(UserDict):
> """Docstring!"""
> ...
> Registry = _Registry()
>
> So Registry is now a globally accessible mutable object; no reason to
> complicate things with singletons or borgs or whathave you. From
> within the interactive console, help(foobar.Registry) gives me the
> _Registry documentation as expected.
>
> From the (Linux) command line though:
> $ pydoc3 foobar._Registry
> [lots of good documentation stuff]
> $ pydoc3 foobar.Registry
> no Python documentation found for 'foobar.Registry'
>
> Is this a thing that can be fixed with a commensurate amount of effort?

There is a test

if not object:
raise ImportError('no Python documentation found for %r' % thing)

in the pydoc module. So all you need is to ensure that your Registry
evaluates to True in a boolean context, e. g. by putting something into it:

$ cat foobar.py
from collections import UserDict

class _Registry(UserDict):
"""Docstring!"""

Registry = _Registry()
Registry["dummy"] = 42
$ pydoc3 foobar.Registry | head -n 10
Help on _Registry in foobar object:

foobar.Registry = class _Registry(collections.UserDict)
| Docstring!
|
| Method resolution order:
| _Registry
| collections.UserDict
| collections.abc.MutableMapping
| collections.abc.Mapping

You might also file a bug report asking to replace

if not object: ...

with

if object is None: ...

Peter Otten

unread,
Jul 8, 2016, 3:45:04 AM7/8/16
to
Peter Otten wrote:

> You might also file a bug report asking to replace

I take that back; the problem is fixed in Python 3.5.

Rustom Mody

unread,
Jul 8, 2016, 4:53:51 AM7/8/16
to
On Friday, July 8, 2016 at 1:15:04 PM UTC+5:30, Peter Otten wrote [slightly edited]
> Peter Otten wrote:
>
> > You might also file a bug report asking to replace
> > if not object: ...
> >
> > with
> >
> >if object is None: ...

>
> I take that back; the problem is fixed in Python 3.5.

Hoo boy!

And then there are those that claim that
bool vs boolishness
true vs True
is cakewalk

Steven D'Aprano

unread,
Jul 8, 2016, 5:21:12 AM7/8/16
to
On Fri, 8 Jul 2016 05:38 pm, Peter Otten wrote:

[...]
>> Is this a thing that can be fixed with a commensurate amount of effort?
>
> There is a test
>
> if not object:
> raise ImportError('no Python documentation found for %r' % thing)
>
> in the pydoc module. So all you need is to ensure that your Registry
> evaluates to True in a boolean context, e. g. by putting something into
> it:


Nicely spotted! I had seen the test but hadn't realised the implications.

Rob Gaddi

unread,
Jul 8, 2016, 12:48:10 PM7/8/16
to
Steven D'Aprano wrote:

> On Fri, 8 Jul 2016 05:38 pm, Peter Otten wrote:
>
> [...]
>>> Is this a thing that can be fixed with a commensurate amount of effort?
>>
>> There is a test
>>
>> if not object:
>> raise ImportError('no Python documentation found for %r' % thing)
>>
>> in the pydoc module. So all you need is to ensure that your Registry
>> evaluates to True in a boolean context, e. g. by putting something into
>> it:
>
>
> Nicely spotted! I had seen the test but hadn't realised the implications.
>

As speedy problem resolutions go, before I mentioned it is pretty good.

Rob Gaddi

unread,
Jul 8, 2016, 12:57:51 PM7/8/16
to
REALLY needs to be an object, preferably dict-like. For instance, one
of the things it does is provide a .getKeyChanged(self, key) method that
returns a keyChanged QSignal so that various elements of the program can
all register for notifications triggered by __setitem__. That way, when
Registry['dut'] gets updated, all of the various GUI elements reliant on
information about the dut all dump their old data and find out about the
newly connected device.

Ethan Furman

unread,
Jul 8, 2016, 4:00:36 PM7/8/16
to
On 07/08/2016 09:57 AM, Rob Gaddi wrote:
> Michael Selik wrote:
>> On Jul 7, 2016, at 7:46 PM, Rob Gaddi <rga...@highlandtechnology.invalid> wrote:

>>> I've got a package that contains a global ensmartened dict that allows
>>> all the various parts of my program to share state.
>>
>> The simplest solution would be to use a module as your singleton. For example, "registry.py" would work. Pydoc will show its docstring, and it will have all the features you had been using, with the added benefit of not needing to enforce its singletonness.
>>
>
> REALLY needs to be an object, preferably dict-like. For instance, one
> of the things it does is provide a .getKeyChanged(self, key) method that
> returns a keyChanged QSignal so that various elements of the program can
> all register for notifications triggered by __setitem__. That way, when
> Registry['dut'] gets updated, all of the various GUI elements reliant on
> information about the dut all dump their old data and find out about the
> newly connected device.

Get the best of both worlds -- insert your Registry object into
sys.modules. It is then importable from anywhere, yet still has all its
native object power.

Something like this should do the trick:

# untested
import sys
sys.modules['%s.registry' % __name__] = _Register()

and then elsewhere:

from blah import registery
registry.whatever()

--
~Ethan~

Lawrence D’Oliveiro

unread,
Jul 13, 2016, 6:42:34 PM7/13/16
to
On Friday, July 8, 2016 at 7:38:56 PM UTC+12, Peter Otten wrote:

> There is a test
>
> if not object:
> raise ImportError('no Python documentation found for %r' % thing)
>
> in the pydoc module. So all you need is to ensure that your Registry
> evaluates to True in a boolean context, e. g. by putting something into it:

And there are still those who think that Python’s lax acceptance of non-boolean values as booleans is a good idea...

Peter Otten

unread,
Jul 13, 2016, 7:54:50 PM7/13/16
to
I don't think this particular problem serves as an argument for stricter
handling of boolean expressions because the fix

if object is not None: ...

is not completely correct, either:

$ cat demo.py
no = False
yes = True
maybe = None
$ pydoc3.4 demo.yes | head -n3
Help on bool in demo object:

demo.yes = class bool(int)
$ pydoc3.4 demo.no | head -n3
no Python documentation found for 'demo.no'

$ pydoc3.5 demo.no | head -n3
Help on bool in demo object:

demo.no = class bool(int)
$ pydoc3.5 demo.maybe | head -n3
No Python documentation found for 'demo.maybe'.
Use help() to get the interactive help utility.
Use help(str) for help on the str class.

Better would be to let the locate() function raise an exception along these
lines:

for part in parts[n:]:
try:
object = getattr(object, part)
except AttributeError:
# return None
raise ImportError("Name ... not found in module ...")

PS: Do the new hints
"""
Use help() to get the interactive help utility.
Use help(str) for help on the str class.
"""
make any sense? Not to me, at this time of the day...

Ian Kelly

unread,
Jul 13, 2016, 8:26:28 PM7/13/16
to
> I don't think this particular problem serves as an argument for stricter
> handling of boolean expressions because the fix
>
> if object is not None: ...
>
> is not completely correct, either:

A better fix would be to have the locate function raise an exception
if the thing is not found instead of returning None.

Rustom Mody

unread,
Jul 16, 2016, 12:04:45 AM7/16/16
to
On Thursday, July 14, 2016 at 5:24:50 AM UTC+5:30, Peter Otten wrote:
> Lawrence D’Oliveiro wrote:
> > And there are still those who think that Python’s lax acceptance of
> > non-boolean values as booleans is a good idea...
>
> I don't think this particular problem serves as an argument for stricter
> handling of boolean expressions because the fix
<details Ive yet to grok snipped>

I was going to apologise for the snark
Then I see thats not my words; I said something along similar lines
Doesn't mean python needs to change
Just that suggesting that python's bool notion is straightforward is an
unnecessary lie – especially to newbies.

Ethan Furman

unread,
Jul 16, 2016, 12:20:13 AM7/16/16
to
On 07/15/2016 09:04 PM, Rustom Mody wrote:

> Just that suggesting that python's bool notion is straightforward is an
> unnecessary lie – especially to newbies.

Python's boolean concept is as simple as it gets -- what is not straightforward about it?

--
~Ethan~

Rustom Mody

unread,
Jul 16, 2016, 1:52:08 AM7/16/16
to
I thought the other thread "Operator precedence/boolean logic" demonstrated that.
Ive added a further continuation there – where this topic is more relevant

Lawrence D’Oliveiro

unread,
Jul 16, 2016, 2:19:56 AM7/16/16
to
The fact that it led to the aforementioned bug.

Chris Angelico

unread,
Jul 16, 2016, 2:29:35 AM7/16/16
to
The difference between ints and floats can lead to bugs, too. Which
one should we eliminate?

Tuple augmented assignment can lead to extremely confusing bugs. Let's
abolish augmented assignment. Or tuples?

Operator precedence leads to bugs when people don't respect it.
Eliminate it; all operators function at the same precedence, with
middle-to-outside associativity (as popularized by the "if/else"
ternary operator).

There. Now we have a bug-free language.

Tongue removed from cheek... The Python policy is a *lot* easier to
work with than REXX's policy is. In REXX, if you put a value in an IF
statement that isn't its canonical True or False (in its case, "1" and
"0"), you get a run-time error. Python lets you use None, False, 0,
etc, as falsey, and if you really want a comparison, you put it in
there. How is this a problem?

As demonstrated elsewhere, the problem isn't the boolification. The
problem is that an 'if' was used where exception handling would have
been far better.

ChrisA

Random832

unread,
Jul 16, 2016, 2:54:14 AM7/16/16
to
On Sat, Jul 16, 2016, at 02:29, Chris Angelico wrote:
> The difference between ints and floats can lead to bugs, too. Which
> one should we eliminate?

Eliminate both of them. Move to a single abstract numeric type* a la
Scheme, with an "inexact" attribute (inexact numbers may or may not be
represented by a float, or by the same bigint/decimal/rational types as
exact ones with a flag set to mark them as inexact.)

*which may have multiple concrete representations, just as our single
abstract unicode string type has different concrete representations for
ASCII, Latin-1, UCS-2, and UCS-4.

Chris Angelico

unread,
Jul 16, 2016, 3:28:01 AM7/16/16
to
Thing is, a Unicode string could be represented in exactly one way
(UCS-4), with identical semantics. Look at Py2's "wide build" (eg most
Linux builds). The rest is just optimization. With a single abstract
numeric type, what exactly does "inexact" mean, where does it come
from, and how does that affect the expected behaviour and performance
of numbers? Will an "Exact" non-integer be stored as Decimal or
Fraction? How do you know? They have vastly different semantics, and
you should be able to choose.

ChrisA

Marko Rauhamaa

unread,
Jul 16, 2016, 3:59:07 AM7/16/16
to
Chris Angelico <ros...@gmail.com>:
> With a single abstract numeric type, what exactly does "inexact" mean,
> where does it come from, and how does that affect the expected
> behaviour and performance of numbers?

Not much is said in the standard:

Thus inexactness is a contagious property of a number. If two
implementations produce exact results for a computation that did not
involve inexact intermediate results, the two ultimate results will
be mathematically equivalent. This is generally not true of
computations involving inexact numbers since approximate methods such
as floating point arithmetic may be used, but it is the duty of each
implementation to make the result as close as practical to the
mathematically ideal result.

<URL: http://www.schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-9.h
tml#%_sec_6.2.2>

Exactness should be considered a flag that expresses whether the result
is an approximation.

> Will an "Exact" non-integer be stored as Decimal or Fraction? How do
> you know? They have vastly different semantics, and you should be able
> to choose.

The manual of the Scheme implementation would likely explain the
particular properties of its number system implementation. At its
simplest, you could have an implementation that only supports, say,
signed 16-bit exact integers. All other numbers would be inexact floats.

Implementations are encouraged, but not required, to support exact
integers and exact rationals of practically unlimited size and
precision, and to implement the above procedures and the / procedure
in such a way that they always return exact results when given exact
arguments. If one of these procedures is unable to deliver an exact
result when given exact arguments, then it may either report a
violation of an implementation restriction or it may silently coerce
its result to an inexact number. Such a coercion may cause an error
later.

An implementation may use floating point and other approximate
representation strategies for inexact numbers. This report
recommends, but does not require, that the IEEE 32-bit and 64-bit
floating point standards be followed by implementations that use
flonum representations, and that implementations using other
representations should match or exceed the precision achievable using
these floating point standards [12].

In particular, implementations that use flonum representations must
follow these rules: A flonum result must be represented with at least
as much precision as is used to express any of the inexact arguments
to that operation. It is desirable (but not required) for potentially
inexact operations such as sqrt, when applied to exact arguments, to
produce exact answers whenever possible (for example the square root
of an exact 4 ought to be an exact 2).

<URL: http://www.schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-9.h
tml#%_sec_6.2.3>


Marko

Steven D'Aprano

unread,
Jul 16, 2016, 4:54:48 AM7/16/16
to
No, that's not going to work. It works for Unicode because the
implementation *really is just a detail*. Whether 'A' is represented as a
seven-bit ASCII code, 8-bit Latin-1 code, 16-bit UCS-2 code or 32-bit UCS-4
code makes no difference to the behaviour of the string. (There may or may
not be performance differences, but that's a separate issue.)

But that doesn't hold for numbers. For a combination of accidental,
intentional and historical reasons, we need to support multiple numeric
types with different behaviour sometimes even different APIs. For example,
different int types behave differently on overflow; floats have signed
zeroes and infinities but fractions don't, etc. But most importantly, one
needs to be able to distinguish between (say) real numbers and complex
numbers, where sqrt(x) and sqrt(x+0j) do not necessarily return the same
value. Or you want to implement (say) "integers modulo 12" such that 11+1
gives 0. You can't do that if you are limited to a single abstract Number
type.


Still, there's probably a lot we could do to improve the ability to
duck-type numbers in Python. For instance, it is a nuisance that we write:

math.isfinite(x)

for floats, but

x.is_finite()

for Decimals.

Steven D'Aprano

unread,
Jul 16, 2016, 5:46:48 AM7/16/16
to
Oh, and a further thought...


On Sat, 16 Jul 2016 04:53 pm, Random832 wrote:

> Eliminate both of them. Move to a single abstract numeric type* a la
> Scheme, with an "inexact" attribute (inexact numbers may or may not be
> represented by a float, or by the same bigint/decimal/rational types as
> exact ones with a flag set to mark them as inexact.)

But that's *wrong*. Numbers are never inexact. (You can have interval
arithmetic using "fuzzy numbers", but they're ALWAYS inexact.) It is
calculations which are exact or inexact, not numbers. There's no a priori
reason to expect that 0.499999 is "inexact" while 0.5 is "exact", you need
to know the calculation that generated it:

py> from decimal import *
py> getcontext().prec = 6
py> Decimal("9.000002")/6 # inexact
Decimal('1.50000')
py> Decimal(1)/2 - Decimal('1e-6') # exact
Decimal('0.499999')


It seems to me that unless you're prepared to actually do some sort of error
tracking, just having an "inexact/exact" flag is pretty useless. If I
perform a series of calculations, and get 1.0 as the result, and the
inexact flag is set, that doesn't mean that 1.0 is the wrong answer -- it
may be that the errors have cancelled and 1.0 is the exact answer. Or it
may be that the error bound is 1.0 ± 10000, and the calculation has
diverged so far from the correct result that it is useless.

Random832

unread,
Jul 16, 2016, 2:04:47 PM7/16/16
to
On Sat, Jul 16, 2016, at 03:27, Chris Angelico wrote:
> Will an "Exact" non-integer be stored as Decimal or
> Fraction? How do you know? They have vastly different semantics, and
> you should be able to choose.

Er, the point is for them to _not_ have different semantics. A decimal
storage format would simply be an optimization for a fraction whose
denominator is a power of 10 (or of 2 and 5)

The semantics of the current Decimal class are those of an inexact
number.

Marko Rauhamaa

unread,
Jul 16, 2016, 2:43:40 PM7/16/16
to
Random832 <rand...@fastmail.com>:
The most common use for Python's Decimal class is *exact* amounts of
currency.

The exactness of a number in Scheme is just a flag. You can force
exactness of a number literal with the #e or #i prefix:

(exact? #e1.2e-7)
==> #t # 1.2e-7 exactly
(exact? #i7)
==> #f # approximately 7


Marko

Chris Angelico

unread,
Jul 16, 2016, 5:02:29 PM7/16/16
to
On Sun, Jul 17, 2016 at 4:04 AM, Random832 <rand...@fastmail.com> wrote:
> On Sat, Jul 16, 2016, at 03:27, Chris Angelico wrote:
>> Will an "Exact" non-integer be stored as Decimal or
>> Fraction? How do you know? They have vastly different semantics, and
>> you should be able to choose.
>
> Er, the point is for them to _not_ have different semantics. A decimal
> storage format would simply be an optimization for a fraction whose
> denominator is a power of 10 (or of 2 and 5)
>
> The semantics of the current Decimal class are those of an inexact
> number.

In that case, an 'Exact' non-integer will have appalling performance -
fractions.Fraction doesn't really work all that nicely when the
numbers start getting huge.

ChrisA

Marko Rauhamaa

unread,
Jul 16, 2016, 5:27:48 PM7/16/16
to
Chris Angelico <ros...@gmail.com>:

> In that case, an 'Exact' non-integer will have appalling performance -
> fractions.Fraction doesn't really work all that nicely when the
> numbers start getting huge.

In Scheme, any math operation is allowed to drop exactness:

If one of these procedures is unable to deliver an exact result when
given exact arguments, then it may either report a violation of an
implementation restriction or it may silently coerce its result to an
inexact number.

<URL: http://www.schemers.org/Documents/Standards/R5RS/HTML/r5r
s-Z-H-9.html#%_sec_6.2.3>


Now, that's neither the recommendation nor the reality; exactness is
preserved at the expense of efficiency. However, that's unlikely to be
an issue in the normal use of Python's Decimal.


Marko

Chris Angelico

unread,
Jul 16, 2016, 6:18:15 PM7/16/16
to
On Sun, Jul 17, 2016 at 7:27 AM, Marko Rauhamaa <ma...@pacujo.net> wrote:
> Chris Angelico <ros...@gmail.com>:
>
>> In that case, an 'Exact' non-integer will have appalling performance -
>> fractions.Fraction doesn't really work all that nicely when the
>> numbers start getting huge.
>
> In Scheme, any math operation is allowed to drop exactness:
>
> If one of these procedures is unable to deliver an exact result when
> given exact arguments, then it may either report a violation of an
> implementation restriction or it may silently coerce its result to an
> inexact number.

The trouble is, repeated addition of fractions is *able* to deliver an
exact result. It just might result in an incredibly slow program. And
then if you mix types, does it aim for the greatest possible
'accuracy', even if that's not quite accurate? (For instance, if you
add 0.2 to 5/8, does it convert to float or to fraction?)

ChrisA

Marko Rauhamaa

unread,
Jul 17, 2016, 3:42:00 AM7/17/16
to
Chris Angelico <ros...@gmail.com>:

> The trouble is, repeated addition of fractions is *able* to deliver an
> exact result. It just might result in an incredibly slow program.

True, although the programmer has control over the feature. If you
*want* the luxury of exact fractions, you pay the price. If you don't,
you make the numbers inexact.

A somewhat analogous situation is there in Python's integers, which have
an unlimited range. The feature is extremely useful in cryptography, for
example (DSA verification is a couple of lines of Python).

> And then if you mix types, does it aim for the greatest possible
> 'accuracy', even if that's not quite accurate? (For instance, if you
> add 0.2 to 5/8, does it convert to float or to fraction?)

Thus inexactness is a contagious property of a number.

<URL: http://www.schemers.org/Documents/Standards/R5RS/HTML/r5r
s-Z-H-9.html#%_sec_6.2.3>

Guile:

(+ 0.2 5/8)
==> 0.825
(exact? (+ 0.2 5/8))
==> #f

Python, for comparison:

>>> 0.2 + fractions.Fraction(5, 8)
0.825
>>> decimal.Decimal("0.1") + 0.1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'decimal.Decimal' and
'float'
>>> fractions.Fraction(5, 8) + decimal.Decimal("0.1")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'Fraction' and 'decim
al.Decimal'


Marko

Chris Angelico

unread,
Jul 17, 2016, 3:52:03 AM7/17/16
to
On Sun, Jul 17, 2016 at 5:41 PM, Marko Rauhamaa <ma...@pacujo.net> wrote:
> Chris Angelico <ros...@gmail.com>:
>
>> The trouble is, repeated addition of fractions is *able* to deliver an
>> exact result. It just might result in an incredibly slow program.
>
> True, although the programmer has control over the feature. If you
> *want* the luxury of exact fractions, you pay the price. If you don't,
> you make the numbers inexact.

Not if you have a single "Number" type:

On Sat, Jul 16, 2016 at 4:53 PM, Random832 <rand...@fastmail.com> wrote:
> Eliminate both of them. Move to a single abstract numeric type* a la
> Scheme, with an "inexact" attribute (inexact numbers may or may not be
> represented by a float, or by the same bigint/decimal/rational types as
> exact ones with a flag set to mark them as inexact.)

Currently yes, you can choose to use fractions.Fraction and pay the
price. How, if you have a single type with different representations,
can you make that choice?

ChrisA

Random832

unread,
Jul 17, 2016, 4:03:58 AM7/17/16
to
On Sun, Jul 17, 2016, at 03:51, Chris Angelico wrote:
> > True, although the programmer has control over the feature. If you
> > *want* the luxury of exact fractions, you pay the price. If you don't,
> > you make the numbers inexact.
>
> Not if you have a single "Number" type:

Saying that exact and inexact numbers can't be a single type is like
saying positive and negative numbers can't be the same type.

Saying that fractions and floats can't be a single type is like saying
ASCII strings and UCS-4 strings can't be the same type within the FSR.
"Single abstract Number type" doesn't preclude a "FNR" where some Number
objects are represented as floats and others are not.

Random832

unread,
Jul 17, 2016, 4:08:36 AM7/17/16
to
On Sun, Jul 17, 2016, at 03:51, Chris Angelico wrote:
> Currently yes, you can choose to use fractions.Fraction and pay the
> price. How, if you have a single type with different representations,
> can you make that choice?

Sorry, I forgot to answer your question. Though, your implicit claim
that it's impossible to make choices if your choices aren't represented
by different types is absurd.

For example, you could have a function that returns an inexact number
with the (approximately) same value as the given number.

Chris Angelico

unread,
Jul 17, 2016, 4:44:54 AM7/17/16
to
Which inexact type, though? Do you get decimal.Decimal, float, or
something else? How do you make that choice? And it's a critical
choice to make. They're not just "inexact numbers". You can have an
exact float (eg 7/2) or an inexact one, and same with Decimal.

ChrisA

Steven D'Aprano

unread,
Jul 17, 2016, 6:35:40 AM7/17/16
to
On Sun, 17 Jul 2016 06:03 pm, Random832 wrote:

> On Sun, Jul 17, 2016, at 03:51, Chris Angelico wrote:
>> > True, although the programmer has control over the feature. If you
>> > *want* the luxury of exact fractions, you pay the price. If you don't,
>> > you make the numbers inexact.
>>
>> Not if you have a single "Number" type:
>
> Saying that exact and inexact numbers can't be a single type is like
> saying positive and negative numbers can't be the same type.

Unless you're talking about about interval arithmetic, "inexact number" is
an oxymoron. Numbers are not inexact or exact, only calculations are.
0.09090909090909091 is just as exact as Fraction(1, 11), they just happen
to be different numbers. The first is exactly:

Fraction(3275345183542179, 36028797018963968)

which is a perfectly good and exact number, precisely equal to:

Fraction(3275345183542178, 36028797018963968) +
Fraction(1, 36028797018963968)

among many other exact calculations. So I would like to know how you justify
claiming that one number is exact and the other is not?

Rustom Mody

unread,
Jul 18, 2016, 12:17:01 AM7/18/16
to
On Saturday, July 16, 2016 at 3:16:48 PM UTC+5:30, Steven D'Aprano wrote:
> On Sat, 16 Jul 2016 04:53 pm, Random832 wrote:
>
> > Eliminate both of them. Move to a single abstract numeric type* a la
> > Scheme, with an "inexact" attribute (inexact numbers may or may not be
> > represented by a float, or by the same bigint/decimal/rational types as
> > exact ones with a flag set to mark them as inexact.)
>
> But that's *wrong*. Numbers are never inexact. (You can have interval
> arithmetic using "fuzzy numbers", but they're ALWAYS inexact.) It is
> calculations which are exact or inexact, not numbers. There's no a priori
> reason to expect that 0.499999 is "inexact" while 0.5 is "exact", you need
> to know the calculation that generated it:

Heh! Did you check what scheme has to say about this before holding forth?
I suggest a tool called google. It can make one seem profound
Here are the first couple of hits it gives (me) for “scheme exact number”


| Scheme integers can be exact and inexact. For example, a number
| written as 3.0 with an explicit decimal-point is inexact, but it
| is also an integer. The functions integer? and scm_is_integer
| report true for such a number, but the functions exact-integer?…
| only allow exact integers and thus report
| false. Likewise, the conversion functions like
| scm_to_signed_integer only accept exact integers.
|
| The motivation for this behavior is that the inexactness of a number
| should not be lost silently. If you want to allow inexact integers,
| you can explicitly insert a call to inexact->exact or to its C
| equivalent scm_inexact_to_exact. (Only inexact integers will be
| converted by this call into exact integers; inexact non-integers
| will become exact fractions.)

https://www.gnu.org/software/guile/manual/html_node/Integers.html

| All numbers are complex numbers. Some of them are real numbers, and
| all of the real numbers that can be represented are also rational
| numbers, except for +inf.0 (positive infinity), +inf.f
| (single-precision variant), -inf.0 (negative infinity), -inf.f
| (single-precision variant), +nan.0 (not-a-number), and +nan.f
| (single-precision variant). Among the rational numbers, some are
| integers, because round applied to the number produces the same
| number.
|
| Orthogonal to those categories, each number is also either an exact
| number or an inexact number. Unless otherwise specified, computations
| that involve an inexact number produce inexact results. Certain
| operations on inexact numbers, however, produce an exact number, such
| as multiplying an inexact number with an exact 0. Operations that
| mathematically produce irrational numbers for some rational arguments
| (e.g., sqrt) may produce inexact results even for exact arguments.

https://docs.racket-lang.org/reference/numbers.html

AIUI…
There are two almost completely unrelated notions of exact

1. ⅓ in decimal cannot be exactly represented though 0.3 0.33 etc are approximations.
We could call these inexact forms of ⅓

2. Measurement and observation produces numbers. These are inexact inherently.

Scheme's notion of exact is towards capturing the second notion.
According to which
“There were 20,000 people in the stadium” would be an inexact integer
[Yeah note Inexact INTEGER]
whereas
√2, e, π are all exact. Just that they dont have finite decimal/continued
fraction and of course float representations.

In short one could think of inexact and exact — in scheme's intended
semantics — as better called scientific (or science-ic) and mathematic
numbers.

Or if you prefer more philosophic jargon: analytic numbers and synthetic numbers:

The fact that analytic/mathematic and synthetic/science-ic domains at all
correspond is at the least surprising.
Famous article calling it “unreasonable” starts with this:

| THERE IS A story about two friends, who were classmates in high
| school, talking about their jobs. One of them became a statistician
| and was working on population trends. He showed a reprint to his
| former classmate. The reprint started, as usual, with the Gaussian
| distribution and the statistician explained to his former classmate
| the meaning of the symbols for the actual population, for the average
| population, and so on. His classmate was a bit incredulous and was not
| quite sure whether the statistician was pulling his leg. "How can you
| know that?" was his query. "And what is this symbol here?" "Oh," said
| the statistician, "this is pi." "What is that?" "The ratio of the
| circumference of the circle to its diameter." "Well, now you are
| pushing your joke too far," said the classmate, "surely the population
| has nothing to do with the circumference of the circle."
| https://www.dartmouth.eduh/~matc/MathDrama/reading/Wigner.html

But the match while strong is not quite perfect:

Physical length (unlike math numbers) may have a ‘least count’
https://en.wikipedia.org/wiki/Planck_length

Likewise time

https://en.wikipedia.org/wiki/Planck_time

And of course all this is highly speculative; ie it may be
https://en.wikipedia.org/wiki/Chronon

At the more mundane level when I read off 2 volts on a voltmeter
- May be reading wrong by seeing from a wrong angle
- Meter may be miscalibrated
- Or broken
- Or the range setting was not 0-10 as I imagined but 0-500
- And so on

IOW numbers picked off from the real world are just naturally wrong

And that's nothing to do with math operations like floating point
introducing errors

Chris Angelico

unread,
Jul 18, 2016, 12:36:11 AM7/18/16
to
On Mon, Jul 18, 2016 at 2:16 PM, Rustom Mody <rusto...@gmail.com> wrote:
> On Saturday, July 16, 2016 at 3:16:48 PM UTC+5:30, Steven D'Aprano wrote:
> Here are the first couple of hits it gives (me) for “scheme exact number”
>
> | Scheme integers can be exact and inexact. For example, a number
> | written as 3.0 with an explicit decimal-point is inexact, but it
> | is also an integer.
>
> AIUI…
> There are two almost completely unrelated notions of exact
>
> 1. ⅓ in decimal cannot be exactly represented though 0.3 0.33 etc are approximations.
> We could call these inexact forms of ⅓
>
> 2. Measurement and observation produces numbers. These are inexact inherently.
>
> Scheme's notion of exact is towards capturing the second notion.

Why does that mean that 3.0 is inexact? In what way is 3.0 "inexact"?
It's an exact value representing the integer three.

ChrisA

Ben Finney

unread,
Jul 18, 2016, 12:46:58 AM7/18/16
to
Rustom Mody <rusto...@gmail.com> writes:

> AIUI…
> There are two almost completely unrelated notions of exact
>
> 1. ⅓ in decimal cannot be exactly represented though 0.3 0.33 etc are
> approximations. We could call these inexact forms of ⅓

Better would be to use the term already used: 0.3333 is an inexact
*representation* of ⅓.

> 2. Measurement and observation produces numbers. These are inexact
> inherently.

What is “those”? The measurement is imprecise, the observations are
inexact.

It makes no sense to say that a number is inexact. Exactness is not a
property of a number. It has one value, which is its identity; it is a
singleton.

> Scheme's notion of exact is towards capturing the second notion.
> According to which
> “There were 20,000 people in the stadium” would be an inexact integer
> [Yeah note Inexact INTEGER]

The number 20 000 is an integer. It has exactly that value.

The number of people may differ (say, 19 997 people), and “20 000
people” is then an inexact representation of the number of people.

> whereas √2, e, π are all exact.

Exactly what?

A number either is π, or it is not. The number π is not exact or
inexact; it simply has one value.

> IOW numbers picked off from the real world are just naturally wrong

The measurement can be wrong. We know that the chances are very high
that the measurement will be imprecise.

How can the *number* be wrong?

You will be able to express yourself much more clearly on this topic
when you cease conflating a number with measurements of that number, or
conflating a number with representations of that number.

--
\ “I know you believe you understood what you think I said, but I |
`\ am not sure you realize that what you heard is not what I |
_o__) meant.” —Robert J. McCloskey |
Ben Finney

Rustom Mody

unread,
Jul 18, 2016, 1:22:47 AM7/18/16
to
On Monday, July 18, 2016 at 10:16:58 AM UTC+5:30, Ben Finney wrote:

> You will be able to express yourself much more clearly on this topic
> when you cease conflating a number with measurements of that number, or
> conflating a number with representations of that number.
>

That more or less sums up (my understanding of) scheme's intent of having
the exact/inexact classification: An inexact number is a measured/observed
number with that data intentionally preserved.
An exact number is just a mathematic number ie a plain ol' number

From the scheme docs I earlier quoted:

| [Motivation for (in)exact...] the inexactness of a number (is a property
| that) should not be lost silently.

As Chris question/example illustrates this may be sufficiently messed up by
floats that the distinction may not be worth making. Dunno... Ive no definite
opinion/data on that. To put it simply float is such a grotesquely
unmathematical type that it is unlikely to cooperate with clean orthogonal
distinctions such as
- Exact/inexact types are orthogonal to the rest of the number hierarchy
- Modelling converts a ‘real-world’ measurement/observation into a mathematical entity
- etc

Rustom Mody

unread,
Jul 18, 2016, 1:38:16 AM7/18/16
to
On Monday, July 18, 2016 at 10:06:11 AM UTC+5:30, Chris Angelico wrote:
[Assuming you are asking in good faith and in the same vein I am answering
without claiming to know all this with much certainty]

I believe we need to distinguish between the intention and its realization
within the syntactic (in this case lexical) structures of the language.

The INTENTION is that in addition to capturing the usual number tower
ℕ ⊂ ℤ ⊂ ℝ (or parts therefore)
scheme also captures ORTHOGONALLY (word in the docs) the (in)exactness attribute

In the realization, the designers need to (over)load these different attributes
onto numeric constants.
So the ruse chosen is that fraction-constants by default are exact
Decimal constants are inexact
And one can override any of these by suitable a function
[At least that's my understanding]

Chris Angelico

unread,
Jul 18, 2016, 1:49:08 AM7/18/16
to
On Mon, Jul 18, 2016 at 3:37 PM, Rustom Mody <rusto...@gmail.com> wrote:
> On Monday, July 18, 2016 at 10:06:11 AM UTC+5:30, Chris Angelico wrote:
>> Why does that mean that 3.0 is inexact? In what way is 3.0 "inexact"?
>> It's an exact value representing the integer three.
>
> [Assuming you are asking in good faith and in the same vein I am answering
> without claiming to know all this with much certainty]

[Yes, I was]

> I believe we need to distinguish between the intention and its realization
> within the syntactic (in this case lexical) structures of the language.
>
> The INTENTION is that in addition to capturing the usual number tower
> ℕ ⊂ ℤ ⊂ ℝ (or parts therefore)
> scheme also captures ORTHOGONALLY (word in the docs) the (in)exactness attribute
>
> In the realization, the designers need to (over)load these different attributes
> onto numeric constants.
> So the ruse chosen is that fraction-constants by default are exact
> Decimal constants are inexact
> And one can override any of these by suitable a function
> [At least that's my understanding]

Ah. Okay. So in theory, you could have exact float literals and
inexact integer literals, if you tag them in some way:

300 ; Exactly 300
300! ; Inexact - roughly 300
3.0 ; Exactly three
3.0! ; Roughly three and zero tenths

This then eliminates the problem of representing exact non-integers
(for instance, IEEE floating point has no problem representing exactly
3.125, but if all floats are automatically "inexact", you lose that
facility), but it then pushes the question of "what does inexact
really MEAN" up to the programmer, at which point it really ends up in
the domain of error values rather than a simple flag "inexact". In
Python, this sort of thing would be perfect as a PyPI package -
"numbers with error values" - which could then define all arithmetic
operations and how they combine error values (with an implicit upcast
from any numeric type to "number with error value of +/- 0"). It
wouldn't need to be part of the core language.

ChrisA

Marko Rauhamaa

unread,
Jul 18, 2016, 2:21:43 AM7/18/16
to
Chris Angelico <ros...@gmail.com>:

> Ah. Okay. So in theory, you could have exact float literals and
> inexact integer literals, if you tag them in some way:
>
> 300 ; Exactly 300
> 300! ; Inexact - roughly 300
> 3.0 ; Exactly three
> 3.0! ; Roughly three and zero tenths

In Scheme:

#e300
#i300
#e3.0
#i3.0

In principle, a Scheme implementation could have exact algebraic numbers
spiked with exact constants like e and π. In practice, exact numbers are
integers and rationals, while inexact numbers are floats and complex
numbers. It is a matter of opinion whether the conceptual abstraction is
worth the confusion.


Marko

Steven D'Aprano

unread,
Jul 18, 2016, 5:29:56 AM7/18/16
to
On Monday 18 July 2016 14:16, Rustom Mody wrote:

> On Saturday, July 16, 2016 at 3:16:48 PM UTC+5:30, Steven D'Aprano wrote:

>> But that's *wrong*. Numbers are never inexact. (You can have interval
>> arithmetic using "fuzzy numbers", but they're ALWAYS inexact.) It is
>> calculations which are exact or inexact, not numbers. There's no a priori
>> reason to expect that 0.499999 is "inexact" while 0.5 is "exact", you need
>> to know the calculation that generated it:
>
> Heh! Did you check what scheme has to say about this before holding forth?
> I suggest a tool called google. It can make one seem profound

Emphasis on the "seem" rather than "actually be" *wink*


> Here are the first couple of hits it gives (me) for “scheme exact number”
[...]
> | The motivation for this behavior is that the inexactness of a number
> | should not be lost silently.

I appreciate the motivation, but I don't think the Scheme, er, scheme is well-
thought out or meaningful. "Exact" or "inexact" is too blunt an instrument to
be of much use. If you do a bunch of calculations, and get a result of 1.0, all
that tells you is that the "true" (i.e. infinitely precise) value is something
possibly centered at 1 with an unknown, not necessarily small, error.

So now you know that *at least one* calculation was inexact, but not which
ones, or the magnitude of the errors introduced.

The Scheme system is effectively the same as a really poor interval arithmetic
system, where numbers can be recorded in two forms:

x ± 0 # exact
x ± ∞ # inexact

and nothing in between.


> AIUI…
> There are two almost completely unrelated notions of exact
>
> 1. ⅓ in decimal cannot be exactly represented though 0.3 0.33 etc are
> approximations.
> We could call these inexact forms of ⅓

But 0.3 is an exact representation of 3/10, 0.1 + 0.2, 0.6/2, etc.


> 2. Measurement and observation produces numbers. These are inexact
> inherently.
>
> Scheme's notion of exact is towards capturing the second notion.

I don't see anything in the Guile documentation you linked to which supports
that interpretation.


> According to which
> “There were 20,000 people in the stadium” would be an inexact integer
> [Yeah note Inexact INTEGER]

Without a bound on the error ("between 0 and 7 billion people, but probably
20,000") that's of very little use.


> whereas
> √2, e, π are all exact. Just that they dont have finite decimal/continued
> fraction and of course float representations.

There are computer algebra systems capable of treating irrationals like √2, e
and π as exact numbers, but I'm pretty sure Guile is not one of them.


> In short one could think of inexact and exact — in scheme's intended
> semantics — as better called scientific (or science-ic) and mathematic
> numbers.

I don't think so. "Science" uses both experimentally-derived numbers (e.g. G,
c, the mass of the electron) and numbers known exactly (√2, e, π).

I think one could better think of Scheme's semantics as a poorly-thought out
hybrid between traditional numerics and a vague approximation to interval
arithmetic.



--
Steve

Marko Rauhamaa

unread,
Jul 18, 2016, 6:00:25 AM7/18/16
to
Steven D'Aprano <steve+comp....@pearwood.info>:

> I think one could better think of Scheme's semantics as a
> poorly-thought out hybrid between traditional numerics and a vague
> approximation to interval arithmetic.

Python programmers (among others) frequently run into issues with
surprising results in floating-point arithmetics. For better or worse,
Scheme has tried to abstract the concept. You don't need to explain the
ideas of IEEE 64-bit floating-point numbers or tie the hands of the
implementation. Instead, what you have is "reliable" arithmetics and
"best-effort" arithmetics, a bit like TCP is "reliable" and UDP is
"best-effort".

"Inexact" means there's a possibility of rounding errors. "Exact" means
no rounding errors were introduced by the limitations of the hardware or
the algorithms. How inexact the inexact results is a complicated topic
for numeric programming.


Marko

Rustom Mody

unread,
Jul 18, 2016, 6:15:12 AM7/18/16
to
On Monday, July 18, 2016 at 2:59:56 PM UTC+5:30, Steven D'Aprano wrote:
> On Monday 18 July 2016 14:16, Rustom Mody wrote:

> > AIUI…
> > There are two almost completely unrelated notions of exact
> >
> > 1. ⅓ in decimal cannot be exactly represented though 0.3 0.33 etc are
> > approximations.
> > We could call these inexact forms of ⅓
>
> But 0.3 is an exact representation of 3/10, 0.1 + 0.2, 0.6/2, etc.
>
>
> > 2. Measurement and observation produces numbers. These are inexact
> > inherently.
> >
> > Scheme's notion of exact is towards capturing the second notion.
>
> I don't see anything in the Guile documentation you linked to which supports
> that interpretation.

Exact example :: index operations into data structures may need to know the index exactly, as may some operations on polynomial coefficients in a symbolic algebra system.
Inexact example :: the results of measurements are inherently inexact, and irrational numbers may be approximated by rational and therefore inexact approximations.

[from the Scheme standard http://www.r6rs.org/final/html/r6rs/r6rs-Z-H-6.html ]

I believe the two clauses:
- measurements inherently inexact
- rational approximations to irrationals

The first represents the basic intention
The second represents the fact that pragmatically we are stuck with things like
floating point as the same chapter indicates at start:


|| This chapter describes Scheme's model for numbers. It is important to
|| distinguish between the mathematical numbers, the Scheme objects that
|| attempt to model them, the machine representations used to implement
|| the numbers, and notations used to write numbers. In this report, the
|| term number refers to a mathematical number, and the term number
|| object refers to a Scheme object representing a number. This report
|| uses the types complex, real, rational, and integer to refer to both
|| mathematical numbers and number objects. The fixnum and flonum types
|| refer to special subsets of the number objects, as determined by
|| common machine representations, as explained below.
||
|| Numbers may be arranged into a tower of subsets in which each level is a subset of the level above it:
||
|| number
|| complex
|| real
|| rational
|| integer
||
|| For example, 5 is an integer. Therefore 5 is also a rational, a real,
|| and a complex. The same is true of the number objects that model 5.
||
|| There is no simple relationship between the subset that contains a
|| number and its representation inside a computer. For example, the
|| integer 5 may have several represen || operations treat number objects as abstract data, as independent of
|| their representation as possible. Although an implementation of Scheme
|| may use many different representations for numbers, this should not be
|| apparent to a casual programmer writing simple programs.

Whether scheme achieves all these laudable and lofty goals of
representation independence, genuine mathematical subsetting (unlike
the usual programming story where float and int are disjoint) etc,
I will along with Marko say: “Cant say if it has turned out practicable”

Practicability has of course many variables
floating point h/w induces floating point languages perpetuates the h/w
perpetuates the languages… etc

Are viable alternatives possible?? Dunno…

Chris Angelico

unread,
Jul 18, 2016, 6:15:26 AM7/18/16
to
On Mon, Jul 18, 2016 at 8:00 PM, Marko Rauhamaa <ma...@pacujo.net> wrote:
> Python programmers (among others) frequently run into issues with
> surprising results in floating-point arithmetics. For better or worse,
> Scheme has tried to abstract the concept. You don't need to explain the
> ideas of IEEE 64-bit floating-point numbers or tie the hands of the
> implementation. Instead, what you have is "reliable" arithmetics and
> "best-effort" arithmetics, a bit like TCP is "reliable" and UDP is
> "best-effort".

The problem with that is that failing to explain IEEE floating point
and just calling it "inexact" scares people off unnecessarily. I've
seen a lot of very intelligent people who think that you should never
compare floats with the == operator, because floats randomly introduce
"inaccuracy". And then you get these sorts of functions:

EPSILON = 0.000001 # Adjust to control numeric accuracy
def is_equal(f1, f2, epsilon=EPSILON):
if abs(f1) > abs(f2):
f1, f2 = f2, f1
return abs(f2-f1) < f1*epsilon

and interminable debates about how to pick an epsilon, whether it
should be relative to the smaller value (as here) or the larger (use
f2 instead), or maybe should be an absolute value, or maybe it should
be relative to the largest/smallest value that was ever involved in
the calculation, or........

Floating point numbers are a representation of real numbers that
involves a certain amount of precision. They're ultimately no
different from grade-school arithmetic where you round stuff off so
you don't need an infinite amount of paper, except that they work with
binary rather than decimal, so people think "0.1 + 0.2 ought to be
exactly 0.3, why isn't it??", and blame floats.

Explain what they REALLY do and how they work, and you'll find they're
not so scary.

ChrisA

Rustom Mody

unread,
Jul 18, 2016, 6:25:12 AM7/18/16
to
On Monday, July 18, 2016 at 3:45:26 PM UTC+5:30, Chris Angelico wrote:
> On Mon, Jul 18, 2016 at 8:00 PM, Marko Rauhamaa wrote:
> > Python programmers (among others) frequently run into issues with
> > surprising results in floating-point arithmetics. For better or worse,
> > Scheme has tried to abstract the concept. You don't need to explain the
> > ideas of IEEE 64-bit floating-point numbers or tie the hands of the
> > implementation. Instead, what you have is "reliable" arithmetics and
> > "best-effort" arithmetics, a bit like TCP is "reliable" and UDP is
> > "best-effort".
>
> The problem with that is that failing to explain IEEE floating point
> and just calling it "inexact" scares people off unnecessarily. I've
> seen a lot of very intelligent people who think that you should never
> compare floats with the == operator, because floats randomly introduce
> "inaccuracy". And then you get these sorts of functions:
>
> EPSILON = 0.000001 # Adjust to control numeric accuracy
> def is_equal(f1, f2, epsilon=EPSILON):
> if abs(f1) > abs(f2):
> f1, f2 = f2, f1
> return abs(f2-f1) < f1*epsilon
>
> and interminable debates about how to pick an epsilon, whether it
> should be relative to the smaller value (as here) or the larger (use
> f2 instead), or maybe should be an absolute value, or maybe it should
> be relative to the largest/smallest value that was ever involved in
> the calculation, or........
>

I dont know what point you are trying to make
Here is behavior. Should one use == ??

Python 2.7.11+ (default, Apr 17 2016, 14:00:29)
[GCC 5.3.1 20160413] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> .1+.1+.1 == .3
False

EPSILON = 0.000001 # Adjust to control numeric accuracy
def is_equal(f1, f2, epsilon=EPSILON):
if abs(f1) > abs(f2):
f1, f2 = f2, f1
return abs(f2-f1) < f1*epsilon
>>> ... ... ... ...

>>> is_equal(.1+.1+.1, .3)
True
>>>

Chris Angelico

unread,
Jul 18, 2016, 6:37:44 AM7/18/16
to
On Mon, Jul 18, 2016 at 8:24 PM, Rustom Mody <rusto...@gmail.com> wrote:
> I dont know what point you are trying to make
> Here is behavior. Should one use == ??
>
> Python 2.7.11+ (default, Apr 17 2016, 14:00:29)
> [GCC 5.3.1 20160413] on linux2
> Type "help", "copyright", "credits" or "license" for more information.
>>>> .1+.1+.1 == .3
> False
>
> EPSILON = 0.000001 # Adjust to control numeric accuracy
> def is_equal(f1, f2, epsilon=EPSILON):
> if abs(f1) > abs(f2):
> f1, f2 = f2, f1
> return abs(f2-f1) < f1*epsilon
>>>> ... ... ... ...
>
>>>> is_equal(.1+.1+.1, .3)
> True
>>>>

Sure, simple equality hasn't given you an "intuitive" result - but
that's because your source code is in decimal. So you need to properly
understand it. If you work with something that can be represented
precisely in binary, you have no problems with equality:

>>> 7/4 + 9/4 + 11/4 + 13/4 == 10
True

It's only the repeating values that have that problem. And if you
disassemble your example, it's obvious why you get False:

>>> dis.dis(lambda: .1+.1+.1 == .3)
1 0 LOAD_CONST 4 (0.30000000000000004)
2 LOAD_CONST 2 (0.3)
4 COMPARE_OP 2 (==)
6 RETURN_VALUE

Of course those two values aren't the same. And it'd be just as
obvious if you looked at them in binary. It'd look like this in
decimal:

0.6667 + 0.6667 + 0.6667 == 2.0

Well, duh, all those intermediate values are rounded up, so you're
getting the sum of the rounding, and of course it's not equal. That's
why you need to get some comprehension of floating-point and how it
*really* functions.

ChrisA

Marko Rauhamaa

unread,
Jul 18, 2016, 7:39:44 AM7/18/16
to
Chris Angelico <ros...@gmail.com>:
> you don't need an infinite amount of paper, except that they work with
> binary rather than decimal, so people think "0.1 + 0.2 ought to be
> exactly 0.3, why isn't it??", and blame floats.

Oh, if we only had eight fingers on our hand...

Scheme, though doesn't force the implementation to use binary. It could
use trinary or sexagesimal for all Scheme cares. The application
shouldn't care, either.


Marko

Peter Otten

unread,
Jul 18, 2016, 8:58:58 AM7/18/16
to
Marko Rauhamaa wrote:

> Chris Angelico <ros...@gmail.com>:
>> you don't need an infinite amount of paper, except that they work with
>> binary rather than decimal, so people think "0.1 + 0.2 ought to be
>> exactly 0.3, why isn't it??", and blame floats.
>
> Oh, if we only had eight fingers on our hand...

We already have one nibble and a carry bit, and it didn't help...

Random832

unread,
Jul 18, 2016, 9:25:23 AM7/18/16
to
On Mon, Jul 18, 2016, at 00:46, Ben Finney wrote:
> What is “those”? The measurement is imprecise, the observations are
> inexact.
>
> It makes no sense to say that a number is inexact. Exactness is not a
> property of a number.

There's no reason it shouldn't be a property of an object of a numeric
type available in a programming environment though.

Random832

unread,
Jul 18, 2016, 9:32:33 AM7/18/16
to
On Mon, Jul 18, 2016, at 01:37, Rustom Mody wrote:
> The INTENTION is that in addition to capturing the usual number tower
> ℕ ⊂ ℤ ⊂ ℝ (or parts therefore)

Well, ℚ. You hardly ever see representations of numbers that are in ℝ-ℚ.

> scheme also captures ORTHOGONALLY (word in the docs) the (in)exactness
> attribute
>
> In the realization, the designers need to (over)load these different
> attributes onto numeric constants. So the ruse chosen is that fraction-
> constants by default are exact Decimal constants are inexact And one
> can override any of these by suitable a function [At least that's my
> understanding]

The other thing you're missing is that implementations are free to
choose any representation they want (such as an IEEE binary float, or a
rational of bounded denominator) for inexact numbers, no matter how they
were written, because they're not required to preserve the exact value.
The fact that an implementation *could* also use an IEEE binary float to
represent an exact rational number whose denominator happens to be power
of two is immaterial to this discussion.

It's not required to actually be "orthogonal" in the sense that you're
imagining - i.e. being able to have inexact numbers whose machine
representations are big integers, big rationals, etc. An implementation
could choose to represent *all* inexact numbers as floats.

Ian Kelly

unread,
Jul 18, 2016, 11:26:27 AM7/18/16
to
Off-topic, c being a fundamental constant is actually in the latter
category. Its *exact* value is 299792458 m/s.

The length of the meter, on the other hand, is defined as the distance
traveled by light in a vacuum in 1/299792458 seconds and is subject to
the precision of measurements.

Marko Rauhamaa

unread,
Jul 18, 2016, 11:40:22 AM7/18/16
to
Ian Kelly <ian.g...@gmail.com>:

> Off-topic, c being a fundamental constant is actually in the latter
> category. Its *exact* value is 299792458 m/s.
>
> The length of the meter, on the other hand, is defined as the distance
> traveled by light in a vacuum in 1/299792458 seconds and is subject to
> the precision of measurements.

Since both c and the second are exact magnitudes, so is the meter.

The second [...] is quantitatively defined in terms of exactly
9,192,631,770 periods of a certain frequency of radiation from the
caesium atom: a so-called atomic clock.
<URL: https://en.wikipedia.org/wiki/Second>


Marko

Marko Rauhamaa

unread,
Jul 18, 2016, 11:56:12 AM7/18/16
to
Marko Rauhamaa <ma...@pacujo.net>:
Which would became immediately apparent if you programmed in Scheme. One
meter is equal to the wavelength of said magnitude times:

9192631770/299792458
==> 656616555/21413747
(exact? 9192631770/299792458)
==> #t


Marko

Ian Kelly

unread,
Jul 18, 2016, 1:14:10 PM7/18/16
to
On Mon, Jul 18, 2016 at 9:55 AM, Marko Rauhamaa <ma...@pacujo.net> wrote:
> Marko Rauhamaa <ma...@pacujo.net>:
>
>> Ian Kelly <ian.g...@gmail.com>:
>>> Off-topic, c being a fundamental constant is actually in the latter
>>> category. Its *exact* value is 299792458 m/s.
>>>
>>> The length of the meter, on the other hand, is defined as the distance
>>> traveled by light in a vacuum in 1/299792458 seconds and is subject to
>>> the precision of measurements.
>>
>> Since both c and the second are exact magnitudes, so is the meter.
>>
>> The second [...] is quantitatively defined in terms of exactly
>> 9,192,631,770 periods of a certain frequency of radiation from the
>> caesium atom: a so-called atomic clock.
>> <URL: https://en.wikipedia.org/wiki/Second>
>
> Which would became immediately apparent if you programmed in Scheme. One
> meter is equal to the wavelength of said magnitude times:

Okay, so how is that wavelength defined?

If you needed to mark a meter stick, and all you had was the
definition of c and the second, how would you do it without measuring
anything?

Marko Rauhamaa

unread,
Jul 18, 2016, 2:58:36 PM7/18/16
to
Ian Kelly <ian.g...@gmail.com>:

> Okay, so how is that wavelength defined?
>
> If you needed to mark a meter stick, and all you had was the
> definition of c and the second, how would you do it without measuring
> anything?

I wouldn't be measuring a meter stick. To measure, say, the height of a
desk, I would bring in some caesium and shine its radiation from the
desk level down to the floor. By counting the ebbs and flows of the
radiation as it leaves the nozzle and strikes the wooden floor I make
the approximage height measurement.

However, I know *exactly* how long a meter is without making a
measurement.


Marko

Ben Finney

unread,
Jul 18, 2016, 8:21:25 PM7/18/16
to
Yes. Because the object is not a number, it is a representation of a
number :-)

--
\ “Truth is stranger than fiction, but it is because fiction is |
`\ obliged to stick to possibilities, truth isn't.” —Mark Twain, |
_o__) _Following the Equator_ |
Ben Finney

Rustom Mody

unread,
Jul 18, 2016, 8:37:05 PM7/18/16
to
On Tuesday, July 19, 2016 at 12:28:36 AM UTC+5:30, Marko Rauhamaa wrote:
> Ian Kelly :
I recollect — school physics textbook so sorry no link —
that in the Newton gravitation law
f = -GMm/r²

there was a discussion about the exponent of r ie 2
And that to some 6 decimal places it had been verified that it was
actually 2.000002

I dont remember all the details
Just that something so obviously to a layman mathematic/analytic as 2
for a physicist may be something calling for experimental verification
ie synthetic/scienceic:
http://plato.stanford.edu/entries/analytic-synthetic/

Steven D'Aprano

unread,
Jul 18, 2016, 11:04:07 PM7/18/16
to
You're right, of course, but that's a post-facto redefinition of both c and
the metre. Historically, the metre was defined first, then people spent a
lot of time measuring the speed of light (I believe it was Galileo who made
the first known attempt). Eventually, physicists decided that it was easier
to declare by fiat that c = 299792458 m/s EXACTLY, and use that definition
to imply a standard metre, rather than keep a standard metre and use that
to measure c.

That makes it a matter of convenience and practicality rather than purity.
It also reflects the current theoretical paradigm that sees c as a constant
and both distance and time subject to distortion. Had special and general
relativity been disproven, or never invented, it's unlikely that we would
have declared c to be more fundamental than distance.

(We haven't declared that G is exactly such-and-such a value, and used that
to define the kilogram.)

Steven D'Aprano

unread,
Jul 18, 2016, 11:16:44 PM7/18/16
to
On Tue, 19 Jul 2016 10:36 am, Rustom Mody wrote:

> I recollect — school physics textbook so sorry no link —
> that in the Newton gravitation law
> f = -GMm/r²
>
> there was a discussion about the exponent of r ie 2
> And that to some 6 decimal places it had been verified that it was
> actually 2.000002

Because gravitational forces are so weak, it is very difficult to
experimentally distinguish (say) an exponent of 1.999999 from 2.000002 from
2 exactly.

Most physicists would say that an experimental result of 2.000002 is pretty
good confirmation that the theoretical power of 2 is correct. Only a very
few would think that the experiment was evidence that both Newtonian and
Einsteinian gravitational theory is incorrect.

(Newton, for obvious reasons; but also general relativity, since Newton's
law can be derived from the "low mass/large distance" case of general
relativity.)

But it's an interesting hypothetical: what if the power wasn't 2 exactly?

Steven D'Aprano

unread,
Jul 18, 2016, 11:21:44 PM7/18/16
to
Yes, there is a reason.

Objects of numeric types in programming environments are intended to model
numbers. Since numbers are not "exact" or "inexact" (but only
calculations), then adding an "exact" attribute to the number makes as much
sense as adding attributes "colour", "weight", or "flavour".

Rustom Mody

unread,
Jul 18, 2016, 11:26:25 PM7/18/16
to
On Tuesday, July 19, 2016 at 8:46:44 AM UTC+5:30, Steven D'Aprano wrote:
> On Tue, 19 Jul 2016 10:36 am, Rustom Mody wrote:
>
> > I recollect — school physics textbook so sorry no link —
> > that in the Newton gravitation law
> > f = -GMm/r²
> >
> > there was a discussion about the exponent of r ie 2
> > And that to some 6 decimal places it had been verified that it was
> > actually 2.000002
>
> Because gravitational forces are so weak, it is very difficult to
> experimentally distinguish (say) an exponent of 1.999999 from 2.000002 from
> 2 exactly.
>
> Most physicists would say that an experimental result of 2.000002 is pretty
> good confirmation that the theoretical power of 2 is correct. Only a very
> few would think that the experiment was evidence that both Newtonian and
> Einsteinian gravitational theory is incorrect.

Yes this was — if memory is right — the conclusion, viz.:
Experimentally it looks like 2.000002 (or whatever)
This is as good as we can measure
So concluding its 2 seems to be reasonable with that 0.000002 relegated to
experimental error

Nevertheless my main point was that such a math (aka analytic to a layman)
looking entity like 2, may for a physicist be a quantity for synthetic verification

>
> (Newton, for obvious reasons; but also general relativity, since Newton's
> law can be derived from the "low mass/large distance" case of general
> relativity.)
>
> But it's an interesting hypothetical: what if the power wasn't 2 exactly?

May be related to the margin of error for G being quite high

Steven D'Aprano

unread,
Jul 18, 2016, 11:42:57 PM7/18/16
to
On Mon, 18 Jul 2016 08:15 pm, Chris Angelico wrote:

> On Mon, Jul 18, 2016 at 8:00 PM, Marko Rauhamaa <ma...@pacujo.net> wrote:
>> Python programmers (among others) frequently run into issues with
>> surprising results in floating-point arithmetics. For better or worse,
>> Scheme has tried to abstract the concept. You don't need to explain the
>> ideas of IEEE 64-bit floating-point numbers or tie the hands of the
>> implementation. Instead, what you have is "reliable" arithmetics and
>> "best-effort" arithmetics, a bit like TCP is "reliable" and UDP is
>> "best-effort".
>
> The problem with that is that failing to explain IEEE floating point
> and just calling it "inexact" scares people off unnecessarily. I've
> seen a lot of very intelligent people who think that you should never
> compare floats with the == operator, because floats randomly introduce
> "inaccuracy".

Yes, this. "Never compare floats for equality" is a pernicious myth that
won't die.


> And then you get these sorts of functions:
>
> EPSILON = 0.000001 # Adjust to control numeric accuracy
> def is_equal(f1, f2, epsilon=EPSILON):
> if abs(f1) > abs(f2):
> f1, f2 = f2, f1
> return abs(f2-f1) < f1*epsilon
>
> and interminable debates about how to pick an epsilon, whether it
> should be relative to the smaller value (as here) or the larger (use
> f2 instead), or maybe should be an absolute value, or maybe it should
> be relative to the largest/smallest value that was ever involved in
> the calculation, or........

Your code is buggy. Consider:

py> is_equal(-1.0, -1.0)
False



> Floating point numbers are a representation of real numbers that
> involves a certain amount of precision. They're ultimately no
> different from grade-school arithmetic where you round stuff off so
> you don't need an infinite amount of paper, except that they work with
> binary rather than decimal, so people think "0.1 + 0.2 ought to be
> exactly 0.3, why isn't it??", and blame floats.

Well, kinda... yes, ultimately deep down you're right. There's nothing
mysterious about floats. The lack of fundamental properties associativity:

(a+b)+c = a+(b+c)

and distributivity:

a×(b+c) = a×b + a×c

are due to numbers being recorded in finite precision, which means that some
calculations are inexact. But the *consequences* of that simple fact are
quite profound, and difficult. Earlier you mentioned "interminable debates
about how to pick an epsilon", but the reason for that is that it is
really, really hard to pick an epsilon in any systematic, objective way.

In the statistics module, I have run into this problem. Where possible, and
surprisingly often, I can test for exact equality. For example, here are a
couple of tests for geometric mean:


def test_multiply_data_points(self):
# Test multiplying every data point by a constant.
c = 111
data = [3.4, 4.5, 4.9, 6.7, 6.8, 7.2, 8.0, 8.1, 9.4]
expected = self.func(data)*c
result = self.func([x*c for x in data])
self.assertEqual(result, expected)

def test_doubled_data(self):
# Test doubling data from [a,b...z] to [a,a,b,b...z,z].
data = [random.uniform(1, 500) for _ in range(1000)]
expected = self.func(data)
actual = self.func(data*2)
self.assertApproxEqual(actual, expected, rel=1e-13)


I didn't hand-tune the constants in test_multiply_data_points, but nor can I
guarantee that if you replace them with other constants of similar
magnitude the assertEqual test will still be appropriate.

In the test_doubled_data case, rounding errors accumulate faster, and cancel
less often, so I use an inexact comparison. Why do I check for a relative
error of 1e-13, rather than 1e-12 or 2.5e-14? *shrug* I can't give an
objective reason for it. It just seems right to me: if the relative error
was much bigger, I'd say that the geometric mean function was too
inaccurate. If it were much smaller, it's too hard for me to have the tests
pass.

Rustom Mody

unread,
Jul 19, 2016, 12:58:50 AM7/19/16
to
On Tuesday, July 19, 2016 at 9:12:57 AM UTC+5:30, Steven D'Aprano wrote:
> On Mon, 18 Jul 2016 08:15 pm, Chris Angelico wrote:
>
> > On Mon, Jul 18, 2016 at 8:00 PM, Marko Rauhamaa wrote:
> >> Python programmers (among others) frequently run into issues with
> >> surprising results in floating-point arithmetics. For better or worse,
> >> Scheme has tried to abstract the concept. You don't need to explain the
> >> ideas of IEEE 64-bit floating-point numbers or tie the hands of the
> >> implementation. Instead, what you have is "reliable" arithmetics and
> >> "best-effort" arithmetics, a bit like TCP is "reliable" and UDP is
> >> "best-effort".
> >
> > The problem with that is that failing to explain IEEE floating point
> > and just calling it "inexact" scares people off unnecessarily. I've
> > seen a lot of very intelligent people who think that you should never
> > compare floats with the == operator, because floats randomly introduce
> > "inaccuracy".
>
> Yes, this. "Never compare floats for equality" is a pernicious myth that
> won't die.

In this context, I asked Chris:
> I dont know what point you are trying to make
> Here is behavior. Should one use == ??

As often happens between me and Chris I ask a ‘why’ (in this case ‘what’) question. And he gives a ‘how’ answer

So I again ask: You say «"Never compare floats for equality" is a pernicious
myth»

Given that for Chris’ is_equal we get
is_equal(.1+.1+.1, .3) is True
whereas for python builtin == its False

What (non)myth do you suggest for replacement?

[Note I am not arguing for the goodness of his is_equal]

Analogy:
Mutable default parameters are a source of problem and confusion.

No A says. One can use them to simulate statics

No B says No problem as long as you make sure there is no mutation to the mutable, either inside or outside the function.

Sure thats all true. However
"Module-globals” is a simpler answer than A
And “DON’T” is simpler than B

So awaiting your preferred myth-ology…

Chris Angelico

unread,
Jul 19, 2016, 1:27:42 AM7/19/16
to
On Tue, Jul 19, 2016 at 1:42 PM, Steven D'Aprano <st...@pearwood.info> wrote:
>> And then you get these sorts of functions:
>>
>> EPSILON = 0.000001 # Adjust to control numeric accuracy
>> def is_equal(f1, f2, epsilon=EPSILON):
>> if abs(f1) > abs(f2):
>> f1, f2 = f2, f1
>> return abs(f2-f1) < f1*epsilon
>>
>> and interminable debates about how to pick an epsilon, whether it
>> should be relative to the smaller value (as here) or the larger (use
>> f2 instead), or maybe should be an absolute value, or maybe it should
>> be relative to the largest/smallest value that was ever involved in
>> the calculation, or........
>
> Your code is buggy. Consider:
>
> py> is_equal(-1.0, -1.0)
> False

Duh, I got the < and <= bug! Shows how easy it is to get this kind of
function wrong. (Even more so, it shows how easy it is to get code
wrong when you type straight into an email and never test it.)

> Earlier you mentioned "interminable debates
> about how to pick an epsilon", but the reason for that is that it is
> really, really hard to pick an epsilon in any systematic, objective way.

Yeah, and that's the problem. If you're working with some concept of
measurement error, what you actually mean is that every number in your
calculation is actually a range centered on that number; which means
that "equality" really means "overlapping ranges". Epsilon-based
equality is just that, only with a global epsilon instead of one that
actually cares about the real error value. How can that NOT be doomed
to failure?

ChrisA

Chris Angelico

unread,
Jul 19, 2016, 1:30:45 AM7/19/16
to
On Tue, Jul 19, 2016 at 2:58 PM, Rustom Mody <rusto...@gmail.com> wrote:
> Analogy:
> Mutable default parameters are a source of problem and confusion.
>
> No A says. One can use them to simulate statics
>
> No B says No problem as long as you make sure there is no mutation to the mutable, either inside or outside the function.
>
> Sure thats all true. However
> "Module-globals” is a simpler answer than A
> And “DON’T” is simpler than B
>
> So awaiting your preferred myth-ology…

Preferred: Understand what's going on. Unless you're talking to a
novice/student programmer (in which case "Oh, don't do that - ask me
about it later when we're not busy fixing this problem" is a valid
response), it's best that people understand what they're working with.

ChrisA

Gene Heskett

unread,
Jul 19, 2016, 8:07:25 AM7/19/16
to
On Monday 18 July 2016 23:16:32 Steven D'Aprano wrote:

> On Tue, 19 Jul 2016 10:36 am, Rustom Mody wrote:
> > I recollect — school physics textbook so sorry no link —
> > that in the Newton gravitation law
> > f = -GMm/r²
> >
> > there was a discussion about the exponent of r ie 2
> > And that to some 6 decimal places it had been verified that it was
> > actually 2.000002
>
> Because gravitational forces are so weak, it is very difficult to
> experimentally distinguish (say) an exponent of 1.999999 from 2.000002
> from 2 exactly.
>
> Most physicists would say that an experimental result of 2.000002 is
> pretty good confirmation that the theoretical power of 2 is correct.
> Only a very few would think that the experiment was evidence that both
> Newtonian and Einsteinian gravitational theory is incorrect.
>
> (Newton, for obvious reasons; but also general relativity, since
> Newton's law can be derived from the "low mass/large distance" case of
> general relativity.)
>
> But it's an interesting hypothetical: what if the power wasn't 2
> exactly?
>
I do not believe it is. The theory of relativity says that the faster you
are going, the more massive you become. Ergo the rate of the
acceleration will decrease as the mass builds up. But the speeds most
of us deal with are so close to at rest that we do not realize in the
everyday world around us, that this does apply at the speeds you throw
that ball while juggling 3 of them. The effect is quite minimal at our
everyday speeds, but there is not a set point where it kicks in, its
always there. Its just that the difference at everyday speeds, is
likely a few hundred digits to the right of the decimal point.

Now, trade those 1 lb balls in on a few quintillion electrons, enough to
account for 5.3 amps of current thru a klystron amplifier tube, and the
acceleration voltage speeding the electrons along is 20,000 volts. That
beam of electrons is trucking right along at a measurable fraction of c
speed. Its also dumping something more than 100KW into the cooling
water flowing thru the bottom of the tube where the beam lands and is
absorbed.

This amplifier does not operate by varying the current like a normal
vacuum tube, it constant current. It is a capacitatively driven tube,
and the power comes back out by being capacitatively coupled from the
electron beam.

How many of you can remember the audio buzz in the UHF channels tv sound
20 years ago?

So I am going to tell you how that buzz became part of the UHF landscape
for so many years, so bear with me as I have a story to tell.

This klystron amplifier, a new one of which was north of $125,000 in the
1970's when I learned about them, is a long tube, around 5 feet long
with alternating sections of copper tubeing and ceramic insulators
separating the copper sections. Typically 4 ceramic sections, each of
which was sealed to a section of copper equiped with contact rings on
each end of the copper sections. A tunable box cavity connected the
copper sections together, bridging the ceramic spacer, so that when the
tube was "dressed" with these cavity's, and lowered into its focusing
magnet, (2200 lbs) you could feed about 1 watt of signal into the top
cavity, which either retarded the velocity of the beam slightly, or
accellerated it a bit. The beam then passed out of that cavity and on
into the next one, tuned a couple megahertz lower, then passed thru the
third cavity normally tuned about 4.2 megahertz higher. Each cavity it
passed thru reinforced this small velocity change until one could
visualize the electrons traveling in little balls by the time it enters
the last cavity, and this cavity has a coupling loop to extract the
amplified signal, 30 kilowatts of it, all because that last cavity is
ringing like a bell because of the capacitative coupling between these
bunched up electrons and the cavity.

The buzz that was so annoying is directly related to the relativistic
effects being modified by the video signal. The electrons gain more mass
as they speed up, so the speed up does not match the slowdown because
they lose mass thereby slowing more, so the net effect is that the tube
gets longer at the high power levels of the synch signal, inventing an
FM signal that is not there in the drive.

Then, since most tv transmitters before digital were actually two
transmitters, one for the video, and one for the audio, and the audio
ran at a constant power level since it was an FM signal, so the aural
was not similarly effected. The old tv's also used the difference
frequency, here in the US of 4.5 megahertz as their aural detection
system. So this FM component to the visual became mixed with the
unaffected audio, injecting this darned buzz into the audio IN your tv.

And relativity, in the form of e=mv2 was the culprit. Not even the FCC
had that figured out.

I had that pointed out to me by a blown water pump breaker, and the lack
of cooling water blew the bottom out of the collector bucket on the
visual tube. About 50 milliseconds after the pump went locked rotor from
the phase failure. After replacing the breaker, I wheeled the aural
tube out of its cubicle and put it into the visual transmitter and tuned
it up for picture service, old tube, got about 80% power out of it.
Then I rigged a cable of aural drive over to the visual and fed about
100 milliwatts of aural drive just to get back on the air while Varian
was building me a new klystron which takes several weeks. At home that
night, checking to see if the viewers might notice, the pix looked ok
but something told me to crank up the sound. Zero buzz, because both
signals were being amplified in the same tube, and subjected to
identical amounts of this distortion, there was no difference to be
detected in the tv itself. The distortion was absolutely in lock step
and totally inaudible to the tv's. With both tubes running normally,
that buzz was only down about 53db at best.

So relativity applies, even to the baseball being thrown by a little
leager. We just do not have the precision to measure it when the effect
is hundreds of digits to the right of the decimal point.

Cheers, Gene Heskett
--
"There are four boxes to be used in defense of liberty:
soap, ballot, jury, and ammo. Please use in that order."
-Ed Howdershelt (Author)
Genes Web page <http://geneslinuxbox.net:6309/gene>

Lawrence D’Oliveiro

unread,
Jul 19, 2016, 1:47:03 PM7/19/16
to
On Wednesday, July 20, 2016 at 12:07:25 AM UTC+12, Gene Heskett wrote:
> This klystron amplifier, a new one of which was north of $125,000 in the
> 1970's when I learned about them, is a long tube, around 5 feet long
> with alternating sections of copper tubeing and ceramic insulators
> separating the copper sections. Typically 4 ceramic sections, each of
> which was sealed to a section of copper equiped with contact rings on
> each end of the copper sections. A tunable box cavity connected the
> copper sections together, bridging the ceramic spacer, so that when the
> tube was "dressed" with these cavity's, and lowered into its focusing
> magnet, (2200 lbs) you could feed about 1 watt of signal into the top
> cavity...

What is this “watt” of which you speak? How much is that in foot-poundals per second?

Gene Heskett

unread,
Jul 19, 2016, 5:17:56 PM7/19/16
to
A unit of electrical power, simplified to 1 volt at 1 amp = 1 watt when
that currant is passed thru a 1 ohm resistor. But since the majority of
radio frequency stuff is designed for a characteristic impedance of 50
ohms, then the currant is 20 milliamps while the voltage rises to 50
volts.

And I am not familiar with this foot-poundals per second that you
question about, but just from the wording I'd say it is a fifty dollar
way to say horsepower. Which is defined in the area of exerting a force
to a 440 pound weight, sufficient to lift that weight one foot in one
second.

Thats for an average horse. I was once in the seat of a stuck in the mud
clear above the drawbar of a 1930's Case LA farm tractor. About 8500
lbs. Daddy whistled up King & Colonial, a pair of perches that between
them weighted a hundred or so above the 4000 pound mark on the dial at
the elevator. :) He also dug out a brace & bit to make a new double-tree
out of a 7 foot length of well seasoned Iowa oak cut full native size of
2" thick by 12" wide. And despite the rationing in effect at the end of
WW-II when this took place, found a lb of sugar cubes for his overall
pocket. Harnessing up the perches, he hooked the traces to this new
double-tree, and cleviced a 75 foot length of 1/2" chain to it. He
brought them down to where the tractor could be reached from fairly dry
ground, drug that chain down and hooked it to the back frame of the 4
bottom 16" plow I was pulling at the time, pulled the hitch pin after
digging down to it, waded back the the perches and took a place where he
could grab the bridals and made tsk tsk noises. Pulling the plow was
done so it would not be in the way. Lead them back and brought the
chain back & hooked it to the drawbar. Walking back to the horses he
had a small handfull of sugar cubes in each hand and gave it to them.
Then grasping the bridals again, a push forward with the tsk tsk. Then a
whoa. They had found they were stuck and would need to put some real
pull on that chain the next time, which they did, digging a trench under
their bellies for about 10 feet when daddy said whoa again. The tractor
had moved. So he gave me instructions to put it in reverse and to be
ready to slam the clutch lever home the next time it moved.

After a breather, wash, rinse and repeat and the tractor was back on dry
ground. At peak pull, that 75 feet of 1/2" log chain was up in the air
about 6" in the middle. Now if any of you know how to convert that
mid-sag amount, the pull on the chain can be deduced, its called the
intercept point method. My guess is that that 4100 lbs of horseflesh
were peaking at 10,000 lbs on the far end of that chain. They of course
can't do it for very long, 10 seconds perhaps, but by then I was loose
and all they were dragging was the chain.

The horses got the rest of that pound of sugar cubes. Those were the two
most gentle giants I have ever lived around. WW-II ended just a couple
months later with V-J day.

Marko Rauhamaa

unread,
Jul 19, 2016, 6:17:20 PM7/19/16
to
Gene Heskett <ghes...@shentel.net>:

> On Tuesday 19 July 2016 13:46:37 Lawrence D’Oliveiro wrote:
>> What is this “watt” of which you speak?
>
> A unit of electrical power, simplified to 1 volt at 1 amp = 1 watt
> when that currant is passed thru a 1 ohm resistor. But since the
> majority of radio frequency stuff is designed for a characteristic
> impedance of 50 ohms, then the currant is 20 milliamps while the
> voltage rises to 50 volts.

Where I live, it is mandatory for stores to display not only prices but
also prices per unit. Unfortunately, the "unit" for batteries is a
piece. Thus, it is not possible to make price comparisons between
different battery brands.

I'd love it if batteries were priced per joule, or even per
kilowatt-hour.

According to <URL: http://www.allaboutbatteries.com/Energy-tables.html>,
an alkaline AA battery holds 0.00260 kWh. Amazon is selling the Duracell
brand at USD 18.38/34-pack, or at about USD 200/kWh.


Marko

Ian Kelly

unread,
Jul 19, 2016, 6:28:04 PM7/19/16
to
On Tue, Jul 19, 2016 at 2:35 PM, Gene Heskett <ghes...@shentel.net> wrote:
> And I am not familiar with this foot-poundals per second that you
> question about, but just from the wording I'd say it is a fifty dollar
> way to say horsepower.

https://en.wikipedia.org/wiki/Foot-poundal

> Which is defined in the area of exerting a force
> to a 440 pound weight, sufficient to lift that weight one foot in one
> second.

1 (imperial) horsepower is 550 (not 440) foot-pounds per second. A
foot-pound is the energy transferred by exerting a 1-pound force
through a displacement of 1 foot. A pound is the force needed to
accelerate 1 pound-mass at 32.174 ft/s**2 (the acceleration of
gravity). A poundal in contrast is the force needed to accelerate 1
pound-mass at 1 ft/s**2. A foot-poundal therefore is the energy
transferred by exerting a 1-poundal force through a displacement of 1
foot. A foot-poundal is thus (approximately) 1/32.174 of a foot-pound.

Multiplying it out, 1 horsepower is approximately 17695.7
foot-poundals per second.

Ah, the machinations that users of imperial units have to endure.

Gregory Ewing

unread,
Jul 19, 2016, 7:08:03 PM7/19/16
to
Gene Heskett wrote:
> The theory of relativity says that the faster you
> are going, the more massive you become.

It doesn't, really. The equations only seem to say that
if you insist on keeping the Newtonian definitions of
momentum and kinetic energy in the context of relativity,
which is a silly thing to do when you think about it.
Physicists realised that nearly a century ago, and no
longer use the idea of a velocity-dependent mass.

--
Greg

Marko Rauhamaa

unread,
Jul 19, 2016, 7:10:08 PM7/19/16
to
Ian Kelly <ian.g...@gmail.com>:

> Ah, the machinations that users of imperial units have to endure.

Europeans often mistakenly believe that Americans haven't yet adopted
the SI units. They have:

- the length of a ski is measured in centimeters

- the width of film and the diameter of a gun barrel are measured in
millimeters

- the wavelength of visible light is measured in nanometers

- the volume of a soda bottle is measured in liters

- a quantity of confiscated narcotics is measured in kilograms

- daily allowance of a vitamin is measured in milligrams

- the pitch of a note is measured in hertz

- a short timespan is measured in seconds


So the problem Europeans have with the situation is *not* the lack of
adoption of new units. Rather, it is the refusal of giving up the
traditional units.

The Anglo-American culture is notorious for its eagerness to absorb
foreign influences. What it abhors is reductionism. There is always room
for more words, ideas, mores, inventions, but nothing is ever deprecated
with a simple edict.


Marko

Marko Rauhamaa

unread,
Jul 19, 2016, 7:20:44 PM7/19/16
to
Gregory Ewing <greg....@canterbury.ac.nz>:
> Physicists realised that nearly a century ago, and no
> longer use the idea of a velocity-dependent mass.

Roche states that about 60% of modern authors just use rest mass and
avoid relativistic mass.

<URL:
https://en.wikipedia.org/wiki/Mass_in_special_relativity#Controversy>


Marko

Lawrence D’Oliveiro

unread,
Jul 19, 2016, 8:01:39 PM7/19/16
to
On Wednesday, July 20, 2016 at 10:28:04 AM UTC+12, Ian wrote:

> Ah, the machinations that users of imperial units have to endure.

Deep in some people’s hearts, the Mars Climate Orbiter still sails...

Random832

unread,
Jul 19, 2016, 11:15:46 PM7/19/16
to
On Tue, Jul 19, 2016, at 18:17, Marko Rauhamaa wrote:
> I'd love it if batteries were priced per joule, or even per
> kilowatt-hour.

Typically their capacity is labeled in amp-hours. You have to know your
devices to know if the voltage difference between different battery
types (Which ranges from 1.2 to 1.7 for nominal-1.5 AAA/AA/C/D cells,
and may be lower under load) is significant or not, and in what
direction. A lower-voltage battery in an incandescent flashlight will
last longer but not be as bright. No idea how it shakes out for LEDs,
motors, or complex electronics. Some devices may not be operable at all
below a certain voltage, and of course the voltage reduces over time as
the battery is drained.

There are just too many variables, and even the nominal amp-hour rating
assumes a certain discharge rate.

And of course, for rechargeable batteries there are even more variables;
but there what you're buying isn't power.

Gene Heskett

unread,
Jul 19, 2016, 11:16:19 PM7/19/16
to
> Ah, the machinations that users of imperial units have to endure.

Thanks for the correction, and the explanation. I should have checked at
wikipedia myself. I don't know where I got the 440 from unless its yards
from the tree to the trap when drag racing. I did a bit of that 60 years
back, discovered it was an expen$ive hobby. Bring lots and lots of
money if you want to play with the big dogs.

Steven D'Aprano

unread,
Jul 20, 2016, 1:43:05 AM7/20/16
to
On Tuesday 19 July 2016 14:58, Rustom Mody wrote:

> So I again ask: You say «"Never compare floats for equality" is a pernicious
> myth»

It is the word *never* which makes it superstition. If people said "Take care
with using == for floats, its often not what you want" I would have no argument
with the statement.

I'd even (reluctantly) accept "usually not what you want". But "never" is out-
and-out cargo-cult programming.


> Given that for Chris’ is_equal we get
> is_equal(.1+.1+.1, .3) is True
> whereas for python builtin == its False
>
> What (non)myth do you suggest for replacement?

Floating point maths is hard, thinking carefully about what you are doing and
whether it is appropriate to use == or a fuzzy almost-equal comparison, or if
equality is the right way at all.

"But thinking is hard, can't you just tell me the answer?"

No. But I can give some guidelines:

Floating point arithmetic is deterministic, it doesn't just randomly mix in
error out of spite or malice. So in principle, you can always estimate the
rounding error from any calculation -- and sometimes there is none.

Arithmetic on integer-values (e.g. 1.0) is always exact, up to a limit of
either 2**53 or approximately 1e53, I forget which. (That's why most Javascript
programmers fail to notice that they don't have an integer type.) So long as
you're using operations that only produce integer values from integer arguments
(such as + - * // but not / ) then all calculations are exact. It is a waste of
time to do:

x = 2.0
y = x*1002.0
is_equal(y, 2004.0, 1e-16)

when you can just do y == 2004.0.


If you do decide to use an absolute error, e.g.:

abs(x - y) < tolerance

keep in mind that your tolerance needs to be chosen relative to the x and y.
For large values of x and y, the smallest possible difference may be very
large:

py> x = 1e80
py> delta = 2**-1000
py> assert delta
py> while x + delta == x:
... delta *= 2
... else:
... print(delta)
...
6.58201822928e+63


So if you're comparing two numbers around 1e80 or so, doing a "fuzzy
comparison" using an absolute tolerance of less than 6.5e63 or so is just a
slow and complicated way of performing an exact comparison using the ==
operator.


Absolute tolerance is faster and easier to understand, and works when the
numbers are on opposite sides of zero, or if one (or both) is zero. But
generally speaking, relative tolerance of one form or another:


abs(x - y) <= abs(x)*relative_tolerance
abs(x - y) <= abs(y)*relative_tolerance
abs(x - y) <= min(abs(x), abs(y))*relative_tolerance
abs(x - y) <= max(abs(x), abs(y))*relative_tolerance

is probably better, but they are slower.

A nice, simple technique is just to round:

if round(x, 6) == round(y, 6):

but that's not quite the same as abs(x-y) < 1e-6.

For library code that cares greatly about precision, using "Unit Last Place"
(ULP) calculations are probably best. But that's a whole different story.


--
Steve

Chris Angelico

unread,
Jul 20, 2016, 2:11:38 AM7/20/16
to
On Wed, Jul 20, 2016 at 3:42 PM, Steven D'Aprano
<steve+comp....@pearwood.info> wrote:
> Arithmetic on integer-values (e.g. 1.0) is always exact, up to a limit of
> either 2**53 or approximately 1e53, I forget which. (That's why most Javascript
> programmers fail to notice that they don't have an integer type.)

It's 2**53, because 64-bit floats use a 53-bit mantissa (52-bits
stored and an implicit 1 at the beginning, although I can never
remember how denormals are represented). Works out to a bit under
1e16. AIUI asm.js offers a 32-bit integer type, which in fall-back
mode is represented with the native "Number" type; for values that
could be stored in a 32-bit integer, a 64-bit float is perfectly
accurate (just stupidly inefficient compared to a real integer type).

ChrisA

Antoon Pardon

unread,
Jul 20, 2016, 3:10:29 AM7/20/16
to
Op 20-07-16 om 07:42 schreef Steven D'Aprano:
> Floating point maths is hard, thinking carefully about what you are doing and
> whether it is appropriate to use == or a fuzzy almost-equal comparison, or if
> equality is the right way at all.
>
> "But thinking is hard, can't you just tell me the answer?"
>
> No. But I can give some guidelines:
>
> Floating point arithmetic is deterministic, it doesn't just randomly mix in
> error out of spite or malice. So in principle, you can always estimate the
> rounding error from any calculation -- and sometimes there is none.

I would like to see a practical example of such an outcome.

> Arithmetic on integer-values (e.g. 1.0) is always exact, up to a limit of
> either 2**53 or approximately 1e53, I forget which. (That's why most Javascript
> programmers fail to notice that they don't have an integer type.) So long as
> you're using operations that only produce integer values from integer arguments
> (such as + - * // but not / ) then all calculations are exact. It is a waste of
> time to do:
>
> x = 2.0
> y = x*1002.0
> is_equal(y, 2004.0, 1e-16)
>
> when you can just do y == 2004.0.

But why perforem integer arithmetics in floats, isn't that a waste of time too?
I really see no reason to use floats if you know all your results will be integers.

--
Antoon.


Marko Rauhamaa

unread,
Jul 20, 2016, 3:17:03 AM7/20/16
to
Random832 <rand...@fastmail.com>:

> On Tue, Jul 19, 2016, at 18:17, Marko Rauhamaa wrote:
>> I'd love it if batteries were priced per joule, or even per
>> kilowatt-hour.
>
> Typically their capacity is labeled in amp-hours.

Did you really see that labeled on the (nonrechargeable AA) battery?

> You have to know your devices to know if the voltage difference
> between different battery types (Which ranges from 1.2 to 1.7 for
> nominal-1.5 AAA/AA/C/D cells, and may be lower under load) is
> significant or not, and in what direction.

Well, your amp hours will be shittier with a lower voltage. That's why
reporting joules would be more honest.


Marko

Marko Rauhamaa

unread,
Jul 20, 2016, 3:25:10 AM7/20/16
to
Antoon Pardon <antoon...@rece.vub.ac.be>:
> But why perforem integer arithmetics in floats,

Conceptual and practical simplificity.

> isn't that a waste of time too?

Probably not, especially compared with the overhead of boxing.


Marko

Steven D'Aprano

unread,
Jul 20, 2016, 8:47:30 AM7/20/16
to
On Wed, 20 Jul 2016 05:09 pm, Antoon Pardon wrote:

> Op 20-07-16 om 07:42 schreef Steven D'Aprano:
>> Floating point maths is hard, thinking carefully about what you are doing
>> and whether it is appropriate to use == or a fuzzy almost-equal
>> comparison, or if equality is the right way at all.
>>
>> "But thinking is hard, can't you just tell me the answer?"
>>
>> No. But I can give some guidelines:
>>
>> Floating point arithmetic is deterministic, it doesn't just randomly mix
>> in error out of spite or malice. So in principle, you can always estimate
>> the rounding error from any calculation -- and sometimes there is none.
>
> I would like to see a practical example of such an outcome.


[steve@ando ~]$ cd /home/steve/python/python-dev/3.4/Lib/test/
[steve@ando test]$ grep self.assertEqual test_statistics.py | wc -l
95


Not all of the 95 examples of using assertEqual apply to float values, but a
good proportion of them do. And if I were a better computer scientist,
there would probably be a lot more assertEquals in my code. A lot of the
time that I do a fuzzy comparison its because I'm too lazy or not good
enough to get a better result.

I am not a good computer scientist. But Bruce Dawson *is* a good computer
scientist:

https://randomascii.wordpress.com/2014/01/27/theres-only-four-billion-floatsso-test-them-all/

Quote:

Conventional wisdom says that you should never compare two floats
for equality – you should always use an epsilon. Conventional
wisdom is wrong.

I’ve written in great detail about how to compare floating-point
values using an epsilon, but there are times when it is just not
appropriate. Sometimes there really is an answer that is correct,
and in those cases anything less than perfection is just sloppy.

So yes, I’m proudly comparing floats to see if they are equal.



>> Arithmetic on integer-values (e.g. 1.0) is always exact, up to a limit of
>> either 2**53 or approximately 1e53, I forget which. (That's why most
>> Javascript programmers fail to notice that they don't have an integer
>> type.) So long as you're using operations that only produce integer
>> values from integer arguments (such as + - * // but not / ) then all
>> calculations are exact. It is a waste of time to do:
>>
>> x = 2.0
>> y = x*1002.0
>> is_equal(y, 2004.0, 1e-16)
>>
>> when you can just do y == 2004.0.
>
> But why perforem integer arithmetics in floats, isn't that a waste of time
> too? I really see no reason to use floats if you know all your results
> will be integers.

In Python, it's probably neither harmful nor useful. The cost of dealing
with boxed values (objects rather than low-level machine values) will
probably outweigh any performance gain one way or the other.

But in lower-level languages, you might find that floating point arithmetic
is faster than integer arithmetic, if you can pass the work on to a FPU
instead of a (slow?) CPU. Or not. It depends on the machine.

Or you might be using a language like Javascript, which intentionally has
only floats for numbers. That's okay, you can still perform exact integer
arithmetic, so long as you stay within the bounds of ±2**16.

Not even in Javascript do you need to write something like this:

x = 0.0
for i in range(20):
x += 1.0

assert abs(x - 20.0) <= 1e-16

alister

unread,
Jul 20, 2016, 9:25:06 AM7/20/16
to
One of my biggest questions since the Brexit vote is can we g back to
using imperial weights & measures (please).




--
Egotist: A person of low taste, more interested in himself than in me.
-- Ambrose Bierce

Marko Rauhamaa

unread,
Jul 20, 2016, 9:55:14 AM7/20/16
to
Steven D'Aprano <st...@pearwood.info>:

> I am not a good computer scientist. But Bruce Dawson *is* a good
> computer scientist:
>
> https://randomascii.wordpress.com/2014/01/27/theres-only-four-billion-f
> loatsso-test-them-all/
>
> Quote:
>
> Conventional wisdom says that you should never compare two floats
> for equality – you should always use an epsilon. Conventional
> wisdom is wrong.
>
> I’ve written in great detail about how to compare floating-point
> values using an epsilon, but there are times when it is just not
> appropriate. Sometimes there really is an answer that is correct,
> and in those cases anything less than perfection is just sloppy.
>
> So yes, I’m proudly comparing floats to see if they are equal.

The point of view in the linked article is very different from that of
most application programming that makes use of floating-point numbers.

Yes, if what you are testing or developing is a numeric or mathematical
package, you should test its numeric/mathematical soundness to the bit.
However, in virtually any other context, you have barely any use for
a floating-point equality comparison because:

1. Floating-point numbers are an approximation of *real numbers*. Two
independently measured real numbers are never equal because under
any continuous probability distribution, the probability of any
given real number is zero. Only continuous ranges can have nonzero
probabilities.

2. Floating-point numbers are *imperfect approximations* of real
numbers. Even when real numbers are derived exactly, floating-point
operations may introduce "lossy compression artifacts" that have to
be compensated for in application programs.

What you have to do exactly to compensate for these challenges depends
on the application, and is very easy to get wrong. However, if an
application programmer is using == to compare two floating-point data
values, it is almost certainly a mistake.

> Or you might be using a language like Javascript, which intentionally
> has only floats for numbers. That's okay, you can still perform exact
> integer arithmetic, so long as you stay within the bounds of ±2**16.
>
> Not even in Javascript do you need to write something like this:
>
> x = 0.0
> for i in range(20):
> x += 1.0
>
> assert abs(x - 20.0) <= 1e-16

Correct because Javascript makes an exactness guarantee of its integers
(I imagine).

In Python, I think it would usually be bad style to rely even on:

1.0 + 1.0 == 2.0

It is very difficult to find a justification for that assumption in
Python's specifications. What we have:

Floating-point numbers are represented in computer hardware as base 2
(binary) fractions.
<URL: https://docs.python.org/3/tutorial/floatingpoint.html>

almost all platforms map Python floats to IEEE-754 “double precision”
<URL: https://docs.python.org/3/tutorial/floatingpoint.html#represent
ation-error>

numbers.Real (float)
These represent machine-level double precision floating point
numbers. You are at the mercy of the underlying machine
architecture (and C or Java implementation) for the accepted range
and handling of overflow.
<URL: https://docs.python.org/3/reference/datamodel.html#the-standar
d-type-hierarchy>


I believe a Python implementation that would have:

1.0 + 1.0 != 2.0

would not be in violation of Python's data model. In fact, even:

1.0 != 1.0

might be totally conformant. For example, we could have a new underlying
real-number technology that stored the value in an *analogous* format
(say, an ultra-precise voltage level) and performed the calculations
using some fast, analogous circuitry.


Marko

Random832

unread,
Jul 20, 2016, 10:00:55 AM7/20/16
to
On Wed, Jul 20, 2016, at 03:16, Marko Rauhamaa wrote:
> Random832 <rand...@fastmail.com>:
> > Typically their capacity is labeled in amp-hours.
>
> Did you really see that labeled on the (nonrechargeable AA) battery?

Sorry, I must have imagined that. Anyway, my point was that the reality
is too complicated to easily assign a number to - that they don't even
try supports that. Duracell's datasheets don't even have a single
number, just a bunch of line graphs.

> > You have to know your devices to know if the voltage difference
> > between different battery types (Which ranges from 1.2 to 1.7 for
> > nominal-1.5 AAA/AA/C/D cells, and may be lower under load) is
> > significant or not, and in what direction.
>
> Well, your amp hours will be shittier with a lower voltage.

Define "shittier". An incandescent flashlight (which consumes less power
at lower voltage) will last longer, but won't be as bright. If it's
still acceptably bright, that's not worse.

> That's why
> reporting joules would be more honest.

And *my* point is that the number of joules depends on how the battery
is used. And different types of batteries are optimized for different
applications.

Chris Angelico

unread,
Jul 20, 2016, 10:26:33 AM7/20/16
to
On Wed, Jul 20, 2016 at 11:54 PM, Marko Rauhamaa <ma...@pacujo.net> wrote:
> 2. Floating-point numbers are *imperfect approximations* of real
> numbers. Even when real numbers are derived exactly, floating-point
> operations may introduce "lossy compression artifacts" that have to
> be compensated for in application programs.

This is the kind of black FUD that has to be fought off. What
"compression artifacts" are introduced? The *only* lossiness in IEEE
binary floating-point arithmetic is rounding. (This is the bit where
someone like Steven is going to point out that there's something else
as well.) Unless you are working with numbers that require more
precision than you have available, the result should be perfectly
accurate. And there are other systems far less 'simple'. Can you
imagine this second assertion failing?

assert x <= y # if not, swap the values
assert x <= (x+y)/2 <= y

Because it can with decimal.Decimal, due to the way rounding happens in decimal.

ChrisA

Marko Rauhamaa

unread,
Jul 20, 2016, 10:59:25 AM7/20/16
to
Chris Angelico <ros...@gmail.com>:

> On Wed, Jul 20, 2016 at 11:54 PM, Marko Rauhamaa <ma...@pacujo.net> wrote:
>> 2. Floating-point numbers are *imperfect approximations* of real
>> numbers. Even when real numbers are derived exactly,
>> floating-point operations may introduce "lossy compression
>> artifacts" that have to be compensated for in application
>> programs.
>
> This is the kind of black FUD that has to be fought off. What
> "compression artifacts" are introduced? The *only* lossiness in IEEE
> binary floating-point arithmetic is rounding.

You are joining me in spreading the FUD. Yes, the immediate lossiness is
rounding, but the effects of that rounding can result in atrocious
accumulative errors in numeric calculations.

> Unless you are working with numbers that require more precision than
> you have available, the result should be perfectly accurate.

Whoa, hold it there! Catastrophic cancellation (<URL:
https://en.wikipedia.org/wiki/Loss_of_significance>) is not a myth:

>>> 0.2 / (0.2 - 0.1)
2.0
>>> 0.2 / ((2e15 + 0.2) - (2e15 + 0.1))
0.8

You can fall victim to the phenomenon when you collect statistics over a
long time. The cumulative sum of a measurement can grow very large,
which causes the naïve per-second rate calculation to become
increasingly bogus.


Marko

Gregory Ewing

unread,
Jul 20, 2016, 6:47:14 PM7/20/16
to
Random832 wrote:
>>Well, your amp hours will be shittier with a lower voltage.
>
> Define "shittier". An incandescent flashlight (which consumes less power
> at lower voltage) will last longer, but won't be as bright. If it's
> still acceptably bright, that's not worse.

I think the point is that the cell will deliver (at most)
the same number of amp-hours at high load as low load,
but if the voltage is lower, those amp-hours will
represent less energy delivered to the load. An amp-hour
that doesn't give you as much energy as you were expecting
could be described as "shitty". :-)

On top of that, the cell might deliver less amp-hours at
high load, for bonus shittiness.

--
Greg

Steven D'Aprano

unread,
Jul 21, 2016, 12:04:24 AM7/21/16
to
On Wed, 20 Jul 2016 11:24 pm, alister wrote:

> One of my biggest questions since the Brexit vote is can we g back to
> using imperial weights & measures (please).

I suppose you might as well -- there's no more empire, no more jobs or
houses, and once the financial traders leave London there'll be no more
money. When Scotland and Northern Ireland leaves there'll be no more United
Kingdom either, and then you and the Welsh can sit around all day trying to
remember how many cubic chains in a hogshead and the number of pints to a
firkin, and blaming the perfidious French and cabbage-eating Huns for
kicking you out of the EU against your will.

England Prevails!

Rustom Mody

unread,
Jul 21, 2016, 1:29:09 AM7/21/16
to
On Wednesday, July 20, 2016 at 11:13:05 AM UTC+5:30, Steven D'Aprano wrote:
> On Tuesday 19 July 2016 14:58, Rustom Mody wrote:
>
> > So I again ask: You say «"Never compare floats for equality" is a pernicious
> > myth»
>
> It is the word *never* which makes it superstition. If people said "Take care
> with using == for floats, its often not what you want" I would have no argument
> with the statement.
>
> I'd even (reluctantly) accept "usually not what you want". But "never" is out-
> and-out cargo-cult programming.

You seem to not understand the realities of teaching.
You (teacher in general) cannot say a saga; only epigrams
You cannot transmit wisdom (even if you own some) just a bit of savviness/cleverness.

So let me ask the question again differently:
How many errors happen by people not using ε-neighborhood checks instead of == checks
How many errors happen by the opposite (mis)use?

IOW “myth”... ok “pernicious myth” Not

BTW APL whose main domain of application is scientific chooses to enshrine
this —equality is ε-neighborhood checking not exact equality checking — into its builtin ‘==’

And http://www.dyalog.com/uploads/documents/Papers/tolerant_comparison/tolerant_comparison.htm

ε is spelt ⎕ct (Comparison Tolerance)
And of course == is spelt =

Chris Angelico

unread,
Jul 21, 2016, 1:35:28 AM7/21/16
to
On Thu, Jul 21, 2016 at 3:28 PM, Rustom Mody <rusto...@gmail.com> wrote:
> ε is spelt ⎕ct (Comparison Tolerance)
> And of course == is spelt =

spelt is spelled spelled. Unless, of course, you mean the wheat variety.

ChrisA

Rustom Mody

unread,
Jul 21, 2016, 1:38:22 AM7/21/16
to
On Wednesday, July 20, 2016 at 8:29:25 PM UTC+5:30, Marko Rauhamaa wrote:
> Chris Angelico :
>
> > On Wed, Jul 20, 2016 at 11:54 PM, Marko Rauhamaa wrote:
> >> 2. Floating-point numbers are *imperfect approximations* of real
> >> numbers. Even when real numbers are derived exactly,
> >> floating-point operations may introduce "lossy compression
> >> artifacts" that have to be compensated for in application
> >> programs.
> >
> > This is the kind of black FUD that has to be fought off. What
> > "compression artifacts" are introduced? The *only* lossiness in IEEE
> > binary floating-point arithmetic is rounding.
>
> You are joining me in spreading the FUD. Yes, the immediate lossiness is
> rounding, but the effects of that rounding can result in atrocious
> accumulative errors in numeric calculations.
>
> > Unless you are working with numbers that require more precision than
> > you have available, the result should be perfectly accurate.
>
> Whoa, hold it there! Catastrophic cancellation (<URL:
> https://en.wikipedia.org/wiki/Loss_of_significance>) is not a myth:

Whose lead para starts:


| Catastrophic cancellation… The effect is that the number of accurate
| (significant) digits in the result is reduced unacceptably. Ways to avoid this
| effect are studied in numerical analysis.

I would go a step further:
The field of numerical analysis came into existence only because this fact
multiplied by the fact that computers do their (inaccurate ≠ inexact) computations
billions of times faster than we do
makes significance a very significant problem!

Rustom Mody

unread,
Jul 21, 2016, 1:52:22 AM7/21/16
to
On Thursday, July 21, 2016 at 11:05:28 AM UTC+5:30, Chris Angelico wrote:
> On Thu, Jul 21, 2016 at 3:28 PM, Rustom Mody wrote:
> > ε is spelt ⎕ct (Comparison Tolerance)
> > And of course == is spelt =
>
> spelt is spelled spelled. Unless, of course, you mean the wheat variety.

Love it!
Though not everyone agrees (including Australians!)
http://english.stackexchange.com/questions/5712/spelt-vs-spelled

Anyway... Ive been collecting quines/self-referential statements for classes
on Theory of computation.

Like these from Douglas Hofstadter.
To which I’ll add yours

You cant have “your cake” and spell it “too”

You cant have your use and mention it too

If this sentence were in Chinese it would say something else

.siht ekil ti gnidaer eb d'uoy ,werbeH ni erew ecnetnes siht fI

Steven D'Aprano

unread,
Jul 21, 2016, 2:34:35 AM7/21/16
to
On Thursday 21 July 2016 15:28, Rustom Mody wrote:

> On Wednesday, July 20, 2016 at 11:13:05 AM UTC+5:30, Steven D'Aprano wrote:
>> On Tuesday 19 July 2016 14:58, Rustom Mody wrote:
>>
>> > So I again ask: You say «"Never compare floats for equality" is a
>> > pernicious myth»
>>
>> It is the word *never* which makes it superstition. If people said "Take
>> care with using == for floats, its often not what you want" I would have no
>> argument with the statement.
>>
>> I'd even (reluctantly) accept "usually not what you want". But "never" is
>> out- and-out cargo-cult programming.
>
> You seem to not understand the realities of teaching.
> You (teacher in general) cannot say a saga; only epigrams

Is "Don't use exact equality unless you know what you're doing" enough of an
epigram for you?


> You cannot transmit wisdom (even if you own some) just a bit of
> savviness/cleverness.

Maybe so, but that's no excuse for transmitting outright misinformation and
superstition. In physics, dealing with motion in the presence of energy losses
is hard, and beginning and intermediate levels of physics will generally
explicitly or implicitly ignore friction and air resistance. But physics
teachers do not teach that "air resistance doesn't exist; you mustn't try to
take friction into account". They teach that it is a simplification.




> So let me ask the question again differently:
> How many errors happen by people not using ε-neighborhood checks instead of
> == checks How many errors happen by the opposite (mis)use?

Precisely 35, and 17812, respectively.


> IOW “myth”... ok “pernicious myth” Not
>
> BTW APL whose main domain of application is scientific chooses to enshrine
> this —equality is ε-neighborhood checking not exact equality checking — into
> its builtin ‘==’

I have a lot of respect for Ken Iverson, and a lot of admiration for language
designers willing to experiment with alternate paradigms.

But keeping in mind that in APL, if you set ⎕ct to 0 you get an exact
comparison, can you find any quotes from Iverson saying that you should *never*
perform exact equality comparisons?



> And
>
http://www.dyalog.com/uploads/documents/Papers/tolerant_comparison/tolerant_comparison.htm

Nice resource, thank you.


> ε is spelt ⎕ct (Comparison Tolerance)
> And of course == is spelt =




--
Steve

Marko Rauhamaa

unread,
Jul 21, 2016, 3:52:44 AM7/21/16
to
Rustom Mody <rusto...@gmail.com>:
> The field of numerical analysis came into existence only because this
> fact multiplied by the fact that computers do their (inaccurate ≠
> inexact) computations billions of times faster than we do makes
> significance a very significant problem!

A couple of related anecdotes involving integer errors.

1. I worked on a (video) product that had to execute a piece of code
every 7 µs or so. A key requirement was that the beat must not drift
far apart from the ideal over time. At first I thought the
traditional nanosecond resolution would be sufficient for the purpose
but then made a calculation:

maximum rounding error = 0.5 ns/7 µs
= 70 µs/s
= 6 s/day

That's why I decided to calculate the interval down to a femtosecond,
whose error was well within our tolerance.

2. After running the LXDE GUI on my 32-bit Linux environment for some
time, the CPU utilization monitor showed the CPU was mysteriously
doing work 100% of the time. The only way out was to reboot the
machine.

After a few months and a few reboots, I investigated the situation
more carefully. It turned out LXDE's CPU meter was reading jiffy
counts from a textual /proc file with scanf("%ld"). Jiffies start
from 0 at the time of the boot and increment every millisecond. Thus,
the maximum signed 32-bit integer is reached in less than 25 days.

When scanf("%ld") overflows, it sets the value to MAX_LONG. That
effectively meant time stopped going forward and all rate
calculations would shoot through the roof. This problem would not
have occurred if the C standard consistently specified modulo
arithmetics for integer operations.

The solution was to use scanf("%lld") instead.


Marko

Chris Angelico

unread,
Jul 21, 2016, 4:47:02 AM7/21/16
to
On Thu, Jul 21, 2016 at 5:52 PM, Marko Rauhamaa <ma...@pacujo.net> wrote:
> A couple of related anecdotes involving integer errors.
>
> 1. I worked on a (video) product that had to execute a piece of code
> every 7 µs or so. A key requirement was that the beat must not drift
> far apart from the ideal over time. At first I thought the
> traditional nanosecond resolution would be sufficient for the purpose
> but then made a calculation:
>
> maximum rounding error = 0.5 ns/7 µs
> = 70 µs/s
> = 6 s/day
>
> That's why I decided to calculate the interval down to a femtosecond,
> whose error was well within our tolerance.

I'd be curious to know whether, had you used nanosecond resolution,
you ever would have seen anything like that +/- 6s/day error. One
convenient attribute of the real world [1] is that, unless there's a
good reason for it to do otherwise [2], random error will tend to
cancel out rather than accumulate. With error of +/- 0.5 ns, assume
(for the sake of argument) that the actual error at each measurement
is random.choice((-0.4, -0.3, -0.2, -0.1, 0.1, 0.2, 0.3, 0.4)) ns,
with zero and the extremes omitted to make the calculations simpler.
In roughly twelve billion randomizations (86400 seconds divided by
7µs), the chances of having more than one billion more positive than
negative are... uhh.... actually, I don't know how to calculate
probabilities off numbers that big, but pretty tiny. So you're going
to have at least 5.5 billion negatives to offset your positives (or
positives to offset your negatives, same diff); more likely they'll be
even closer. So if you have (say) 5.5 to 6.5 ratio of signs, what
you're actually working with is half a second per day of accumulated
error - and I think you'd have a pretty tiny probability of even
*that* extreme a result. If it's more like 5.9 to 6.1, you'd have 0.1
seconds per day of error, at most. Plus, the same probabilistic
calculation can be done for days across a month, so even though the
theory would let you drift by three minutes a month, the chances of
shifting by even an entire second over that time are fairly slim.

This is something where I'd be more worried about systematic bias in
the code than anything from measurement or rounding error.

(I don't believe I've ever actually used a computer that's capable of
nanosecond-accurate time calculations. Generally they return time in
nanoseconds for consistency, but they won't return successive integer
values. You must have been on some seriously high-end hardware -
although that doesn't surprise me much, given that you were working on
a video product.)

ChrisA

[1] Believe you me, it has no shortage of INconvenient attributes, so
it's nice to have one swing the balance back a bit!
[2] If there's systematic error - if your 7 µs is actually averaging
7.25 µs - you need to deal with that separately.

Marko Rauhamaa

unread,
Jul 21, 2016, 5:09:25 AM7/21/16
to
Chris Angelico <ros...@gmail.com>:

> On Thu, Jul 21, 2016 at 5:52 PM, Marko Rauhamaa <ma...@pacujo.net> wrote:
>> A couple of related anecdotes involving integer errors.
>>
>> 1. I worked on a (video) product that had to execute a piece of code
>> every 7 µs or so. A key requirement was that the beat must not drift
>> far apart from the ideal over time. At first I thought the
>> traditional nanosecond resolution would be sufficient for the purpose
>> but then made a calculation:
>>
>> maximum rounding error = 0.5 ns/7 µs
>> = 70 µs/s
>> = 6 s/day
>>
>> That's why I decided to calculate the interval down to a femtosecond,
>> whose error was well within our tolerance.
>
> I'd be curious to know whether, had you used nanosecond resolution,
> you ever would have seen anything like that +/- 6s/day error. One
> convenient attribute of the real world [1] is that, unless there's a
> good reason for it to do otherwise [2], random error will tend to
> cancel out rather than accumulate. With error of +/- 0.5 ns, assume
> (for the sake of argument) that the actual error at each measurement
> is random.choice((-0.4, -0.3, -0.2, -0.1, 0.1, 0.2, 0.3, 0.4)) ns,

No, this is a systematic error due to the rounding of a rational number
to the nearest nanosecond interval. Systematic errors of this kind are a
real thing and not even all that uncommon.

> (I don't believe I've ever actually used a computer that's capable of
> nanosecond-accurate time calculations. Generally they return time in
> nanoseconds for consistency, but they won't return successive integer
> values. You must have been on some seriously high-end hardware -
> although that doesn't surprise me much, given that you were working on
> a video product.)

Nanosecond, even femtosecond, calculations are trivially simple integer
arithmetics that can be performed with pencil and paper. The hardware
was nothing fancy, and the timing error due to various hardware,
software and network realities was in the order of ±100 µs. That was
tolerable and could be handled through buffering. However, a cumulative
error of 6 seconds per day was *not* tolerable.

The calculations needed to be extremely simple because the interrupt
routine had to execute every 7 microseconds. You had to let the hardware
RTC do most of the work and do just a couple of integer operations in
the interrupt routine. In particular, you didn't have time to
recalculate and reprogram the RTC at every interrupt.


Marko

Rustom Mody

unread,
Jul 21, 2016, 9:14:30 AM7/21/16
to
On Thursday, July 21, 2016 at 12:04:35 PM UTC+5:30, Steven D'Aprano wrote:
> On Thursday 21 July 2016 15:28, Rustom Mody wrote:
> > BTW APL whose main domain of application is scientific chooses to enshrine
> > this —equality is ε-neighborhood checking not exact equality checking — into
> > its builtin ‘==’
>
> I have a lot of respect for Ken Iverson, and a lot of admiration for language
> designers willing to experiment with alternate paradigms.

This choice has significant(!!) costs: Fuzzy equality is not transitive:
One can get
a = b ∧ b = c ∧ a ≠ c
>
> But keeping in mind that in APL, if you set ⎕ct to 0 you get an exact
> comparison, can you find any quotes from Iverson saying that you should *never*
> perform exact equality comparisons?

There you go with your strawmen!
Remember it was you (and Chris) who expressed extreme positions:
“Pernicious myth” “FUD” etc

Steven D'Aprano

unread,
Jul 21, 2016, 12:10:29 PM7/21/16
to
And YOU'RE the one who is raising APL as an argument *against* my
characterisation.

Do you think that Iverson would agree with the conventional wisdom that we
should NEVER test floats for exact equality?

Do you know of ANY expert in numeric computation who will agree with the
conventional wisdom? If so, who?

I'll admit that I've stolen my description of this rule as "superstition"
from perhaps the world's foremost authority on numeric computation,
Professor William Kahan. (See the forward to "Apple Numerics Manual, Second
Edition, 1988.) You don't like my use of the term "pernicious"? In my
opinion, any conventional wisdom which keeps people *more* rather than
*less* ignorant is pernicious. Anything which discourages them from testing
their numeric functions to the full precision possible is pernicious.
Anything which encourages the idea that numeric computation using floats is
non-deterministic is pernicious.

But if you don't agree, feel free to dismiss the word as mere hyperbola and
MOVE ON. You don't have to nit pick about every word I use.

The bottom line is, while it is often true that using exact equality is
going to surprise people, the conventional wisdom to NEVER do so is both
(1) factually wrong, there are plenty of examples where one can and should
use exact equality, and (2) rather useless, as the conventional wisdom
gives no clue as to the practicalities of what to replace it with.
It is loading more messages.
0 new messages