Integer division with / - request explanation of behavior

Today I discovered the difference in the meaning of the / (arithmetic
divide) method depending on whether it's caller is an integer or a
float.

I discovered that I had to cast the calling number explicitly to a float
and it seemed totally non-intuitive to me.

A couple of points:

1) I just discovered that this behavior exists in Java and C as well.
Which, frankly, I didn't even realize. Sigh.

2) I've read some other posts and people have mentioned the notion of
type purity with respect to this. I don't see why that's a problem.
When one divides two integers, one isn't asking for one of the integer
arguments to be cast to a float, they're asking for the result of
dividing two integers. Since when is it not allowable for a method to
take arguments of a given type and return a result of a different type?

A couple of questions:

1) I see that there is a divmod operator in Ruby that returns the
quotient and remainder of a division. Why is the overridden / operator
necessary when there is already a way to get int1 DIV int2 by using
int1.divmod(int2)[0]?

2) Is the reason for the behavior of "/" is that this is the behavior of
"/" in C? Why is it that way in C?

Thanks,
Wes

···

--
Posted via http://www.ruby-forum.com/.

Wes Gamble wrote:

Today I discovered the difference in the meaning of the / (arithmetic
divide) method depending on whether it's caller is an integer or a
float.

Not exactly. The result is expressed in the type of the more precise of the
two operands.

I discovered that I had to cast the calling number explicitly to a float
and it seemed totally non-intuitive to me.

Well, that depends on what you want as a result. You aren't required to cast
one of the operands as a float. Maybe you want the default result for the
provided values.

I often break a time value into hours, minutes and seconds. I do this by
successive application of integer modulo and divide. If the division
operator were to promote my values, the algorithm would fail.

A couple of points:

1) I just discovered that this behavior exists in Java and C as well.
Which, frankly, I didn't even realize. Sigh.

There are excellent reasons for this behavior. When you divide two numbers,
the result should have the precision of the more precise type of either of
the two operands.

2) I've read some other posts and people have mentioned the notion of
type purity with respect to this. I don't see why that's a problem.

It's not about type purity. That isn't supported by the fact that the less
precise type is discarded in favor of the more precise type.

When one divides two integers, one isn't asking for one of the integer
arguments to be cast to a float, they're asking for the result of
dividing two integers. Since when is it not allowable for a method to
take arguments of a given type and return a result of a different type?

It is not a question of allowed, it is a question of what one would expect
without explicit adjustment.

A couple of questions:

1) I see that there is a divmod operator in Ruby that returns the
quotient and remainder of a division. Why is the overridden / operator
necessary when there is already a way to get int1 DIV int2 by using
int1.divmod(int2)[0]?

Because people expect to be able to use a division operator for division.

2) Is the reason for the behavior of "/" is that this is the behavior of
"/" in C? Why is it that way in C?

This behavior is common to all modern languages. It exists because the
languages that support it are designed to act on a set of common-sense
assumptions.

BTW, the behavior goes beyond integers and floats. It also applies to
extended-precision numerical types.

x = BigDecimal.new("3.0",100)

puts 1/x

0.3333333333333333333333333333333333333333333333333333333333333333333\
33333333333333333333333333333333333333333333333333333E0

One of the operands is an integer, but the result is cast to the precision
of the more precise type. So much for type purity.

···

--
Paul Lutus
http://www.arachnoid.com

Hello !

2) Is the reason for the behavior of "/" is that this is the behavior of
"/" in C? Why is it that way in C?

  Here's a couple of reasons:

  * C is mapping this operation directly to assembly. Old x86 processors
used to be able to manipulate only integers, so the result of the
division of one integer by another had to be an integer;

  * the architecture for processing floats is way more complex and less
portable than the one from integers (integer arithmetic is the same on
every single processor in the world; float arithmetic is a nightmare);

  * floats are much slower to manipulate, even in assembly code;

  * in ruby, integers are hard-coded as immediate values, whereas floats
are embedded into a complex data structure. You wouldn't want to invoke
a really heavy machinery for an integer division...

  Does that sound correct to you ?

  Cheers,

  Vince

Wes Gamble wrote:

Today I discovered the difference in the meaning of the / (arithmetic
divide) method depending on whether it's caller is an integer or a
float.

I discovered that I had to cast the calling number explicitly to a float
and it seemed totally non-intuitive to me.

The mathn namespace-clobbering module makes maths work like expected.

The magic lies in aliasing Fixnum#/ to Fixnum#quo (same for Bignum).

You could use that method explicitly, or just clobber the classes if
you're sure nothing else expects the C meaning to work.

I frankly think there are two reasons for it
(1) Matz thaught it is more useful that way
and/or
(2) Matz thaught it is POLS
these are good reasons of course ;).
I also believe that most users are quite happy with it, I am BTW ;), there
are of course applications to be written in Ruby
where the behavior the other way round would be more useful....
... happy monkeypatching!

Cheers
Robert

···

On 9/30/06, Paul Lutus <nospam@nosite.zzz> wrote:

Wes Gamble wrote:
<snip>

--
Deux choses sont infinies : l'univers et la bêtise humaine ; en ce qui
concerne l'univers, je n'en ai pas acquis la certitude absolue.

- Albert Einstein

Paul Lutus wrote:

2) Is the reason for the behavior of "/" is that this is the behavior of
"/" in C? Why is it that way in C?

This behavior is common to all modern languages. It exists because the
languages that support it are designed to act on a set of common-sense
assumptions.

BTW, the behavior goes beyond integers and floats. It also applies to
extended-precision numerical types.

And as far as I know it's even an IEEE standard. Programming systems better comply with it in order to make results comparable and interchangeable.

Kind regards

  robert

Actually, integers are more precise than IEEE floating points
since 2.2 - 1.2 != 1.0 :slight_smile: s/precise/accurate !

···

On 2006.09.30 18:25, Paul Lutus wrote:

Wes Gamble wrote:

> Today I discovered the difference in the meaning of the / (arithmetic
> divide) method depending on whether it's caller is an integer or a
> float.

Not exactly. The result is expressed in the type of the more precise of the
two operands.

Eero Saynatkari wrote:

···

On 2006.09.30 18:25, Paul Lutus wrote:

Wes Gamble wrote:

> Today I discovered the difference in the meaning of the / (arithmetic
> divide) method depending on whether it's caller is an integer or a
> float.

Not exactly. The result is expressed in the type of the more precise of
the two operands.

Actually, integers are more precise than IEEE floating points
since 2.2 - 1.2 != 1.0 :slight_smile: s/precise/accurate !

Yes, I used the wrong term. I should have said "longer" rather than more
precise. Even that is less true than it used to be, as what is generally
accepted to be an int changes over time.

Float and double math is at least reliable in its unreliability. :slight_smile:

--
Paul Lutus
http://www.arachnoid.com

Robert Klemme wrote:

/ ...

BTW, the behavior goes beyond integers and floats. It also applies to
extended-precision numerical types.

And as far as I know it's even an IEEE standard.

I think that's true also, but certainly type promotion is what people expect
to happen.

Programming systems
better comply with it in order to make results comparable and
interchangeable.

There's a can of worms. It turns out the behavior of the different languages
WRT conversion from and to base ten leads to some borderline failures if
the textual forms are transferred between environments.

As it turns out Perl is one of the worst as far as being able to recreate
its own internal binary representation based on its self-generated textual
representation. I became comfortable (perhaps too comfortable) with being
able to convert doubles back and forth between string and binary form,
reliably and repeatably, in most languages, but I couldn't make this happen
in Perl (version 4.0 IIRC).

Without realizing it, I had come to assume that a language's base ten
textual representation for a double or a float would be readable by that
same language and when reconverted (base ten -> base two) produce an exact
copy of the original binary form, and this is true in most languages. Then
a Perl programmer challenged me on this, saying the base ten representation
almost never recreated the original binary number, and I tried to show that
wasn't true. I wrote test suites in Java, C and C++ (the latter not using
printf and scanf) and Perl, and the results were perfect in every language
except Perl.

At this point, that observation may be more history than fact, because of
the increasing importance of data transfers between environments.

···

--
Paul Lutus
http://www.arachnoid.com

I frankly think there are two reasons for it
(1) Matz thaught it is more useful that way
and/or
(2) Matz thaught it is POLS
these are good reasons of course ;).

POLS?

···

--
Posted via http://www.ruby-forum.com/\.

Not on all platforms. For instance, in Ocaml, it's true:

# 2. -. 1. = 1.;;
- : bool = true

···

On 06-09-30, at 11:11, Eero Saynatkari wrote:

On 2006.09.30 18:25, Paul Lutus wrote:

Wes Gamble wrote:

Today I discovered the difference in the meaning of the / (arithmetic
divide) method depending on whether it's caller is an integer or a
float.

Not exactly. The result is expressed in the type of the more precise of the
two operands.

Actually, integers are more precise than IEEE floating points
since 2.2 - 1.2 != 1.0 :slight_smile: s/precise/accurate !

--
Jeremy Tregunna
jtregunna@blurgle.ca

Paul Lutus wrote:

Without realizing it, I had come to assume that a language's base ten
textual representation for a double or a float would be readable by that
same language and when reconverted (base ten -> base two) produce an exact
copy of the original binary form, and this is true in most languages. Then
a Perl programmer challenged me on this, saying the base ten representation
almost never recreated the original binary number, and I tried to show that
wasn't true. I wrote test suites in Java, C and C++ (the latter not using
printf and scanf) and Perl, and the results were perfect in every language
except Perl.

At this point, that observation may be more history than fact, because of
the increasing importance of data transfers between environments.

Long ago in a galaxy far away, there were many more choices for transfer
of data from one machine to another. And someone coined the rule "The
receiver makes it right".

Wes Gamble wrote:

I frankly think there are two reasons for it
(1) Matz thaught it is more useful that way
and/or
(2) Matz thaught it is POLS
these are good reasons of course ;).

POLS?

Principle Of Least Surprise.

Paul Lutus wrote:

Robert Klemme wrote:

/ ...

BTW, the behavior goes beyond integers and floats. It also applies to
extended-precision numerical types.

And as far as I know it's even an IEEE standard.

I think that's true also, but certainly type promotion is what people expect
to happen.

In this case I lean on the standard's side: numerics are just too basic and fundamental to let implementers of languages do what they like. I know a case where a legacy system doing static calculus was replaced by a new system on a totally different OS platform. Data was migrated and afterwards people complained that the new system was doing the match wrong. It turned out that it was the *old* system that actually had the math wrong. They were lucky that in years no building crashed because of this...

Programming systems better comply with it in order to make results comparable and
interchangeable.

There's a can of worms. It turns out the behavior of the different languages
WRT conversion from and to base ten leads to some borderline failures if
the textual forms are transferred between environments.

I am sure, conversion is yet another standard. :slight_smile: Or maybe not:

As it turns out Perl is one of the worst as far as being able to recreate
its own internal binary representation based on its self-generated textual
representation. I became comfortable (perhaps too comfortable) with being
able to convert doubles back and forth between string and binary form,
reliably and repeatably, in most languages, but I couldn't make this happen
in Perl (version 4.0 IIRC).

Without realizing it, I had come to assume that a language's base ten
textual representation for a double or a float would be readable by that
same language and when reconverted (base ten -> base two) produce an exact
copy of the original binary form, and this is true in most languages. Then
a Perl programmer challenged me on this, saying the base ten representation
almost never recreated the original binary number, and I tried to show that
wasn't true. I wrote test suites in Java, C and C++ (the latter not using
printf and scanf) and Perl, and the results were perfect in every language
except Perl.

One more reason to not use Perl. :slight_smile: The question is whether one should rely on the binary <-> text conversion. The best for decimal accuracy is probably BCD anyway...

Kind regards

  robert

used an abbriviation,
no honestly it is kind of a standard in this ML, but I should have taken the
time to spell it out of course.

Robert

···

On 9/30/06, Wes Gamble <weyus@att.net> wrote:

> I frankly think there are two reasons for it
> (1) Matz thaught it is more useful that way
> and/or
> (2) Matz thaught it is POLS
> these are good reasons of course ;).

POLS?

--
Posted via http://www.ruby-forum.com/\.

Sorry, sorry, I wanted to seem intelligent and educated and informed so I

--
Deux choses sont infinies : l'univers et la bêtise humaine ; en ce qui
concerne l'univers, je n'en ai pas acquis la certitude absolue.

- Albert Einstein

Jeremy Tregunna wrote:

Actually, integers are more precise than IEEE floating points
since 2.2 - 1.2 != 1.0 :slight_smile: s/precise/accurate !

Not on all platforms. For instance, in Ocaml, it's true:

# 2. -. 1. = 1.;;
- : bool = true

Your example works because integers are rational IEEE floating point
numbers. Problems arise when you use a number that's a rational decimal
number, but an irrational IEEE binary floating point one. Those aren't
precise no matter what storage size you use.

# 2.2 -. 1.2;;
- : float = 1.0000000000000002
# (2.2 -. 1.2) != 1.0;;
- : bool = true

For this example, Ruby's rounding earlier loses the imprecision.

Ripping off a tutorial article on IEEE floats[1] produces an example
that manifests in Ruby (also in OCaml):

irb(main):001:0> a = 0.0
=> 0.0
irb(main):002:0> 10000.times {
irb(main):003:1* a += 0.0001
irb(main):004:1> }
=> 10000
irb(main):005:0> a
=> 0.999999999999906
irb(main):006:0>

David Vallner

[1] Microsoft Support

Jeremy Tregunna <jtregunna@blurgle.ca> writes:

Wes Gamble wrote:

Today I discovered the difference in the meaning of the /
(arithmetic
divide) method depending on whether it's caller is an integer or a
float.

Not exactly. The result is expressed in the type of the more
precise of the
two operands.

Actually, integers are more precise than IEEE floating points
since 2.2 - 1.2 != 1.0 :slight_smile: s/precise/accurate !

Not on all platforms. For instance, in Ocaml, it's true:

# 2. -. 1. = 1.;;
- : bool = true

No, it doesnt.

Darwin lilith 7.9.0
Objective Caml version 3.08.3
# 2.2 -. 1.2 = 1.0;;
- : bool = false

Due to how IEEE floats work, all operations on whole numbers will
always be exact.

···

On 06-09-30, at 11:11, Eero Saynatkari wrote:

On 2006.09.30 18:25, Paul Lutus wrote:

Jeremy Tregunna

--
Christian Neukirchen <chneukirchen@gmail.com> http://chneukirchen.org

I kinna start to love that guy :wink:

···

On 9/30/06, M. Edward (Ed) Borasky <znmeb@cesmail.net> wrote:

Long ago in a galaxy far away, there were many more choices for transfer
of data from one machine to another. And someone coined the rule "The
receiver makes it right".

--
Deux choses sont infinies : l'univers et la bêtise humaine ; en ce qui
concerne l'univers, je n'en ai pas acquis la certitude absolue.

- Albert Einstein

Robert Klemme wrote:

/ ...

I
know a case where a legacy system doing static calculus was replaced by
a new system on a totally different OS platform. Data was migrated and
afterwards people complained that the new system was doing the match
wrong. It turned out that it was the *old* system that actually had the
math wrong. They were lucky that in years no building crashed because
of this...

That's a great story. I hope its details are written up somewhere. You may
be aware there is a lot of academic interest in examples where erroneous
computer results come to be accepted, even defended as accurate.

I am reminded of a scene in "Rain Man" in which the idiot savant played by
Dustin Hoffman is asked to provide a difficult mathematical result, while
the questioner simultaneously computes it on a calculator. The savant
replies with the exact number of decimal places that the calculator
produces, no more, no less, for a problem that produces an irrational
result. This is obviously for the benefit of the nonspecialist in the
audience, who would have been *less* impressed if the savant had offered
more digits than the calculator -- those extra digits couldn't possibly be
real, could they, otherwise the calculator would have provided them.

/ ...

There's a can of worms. It turns out the behavior of the different
languages WRT conversion from and to base ten leads to some borderline
failures if the textual forms are transferred between environments.

I am sure, conversion is yet another standard. :slight_smile: Or maybe not:

I think this is part of a standard, and it's usually followed to the letter.

/ ...

The question is whether one should
rely on the binary <-> text conversion. The best for decimal accuracy
is probably BCD anyway...

Yes. My point is that this business of converting between binary and
text/base-ten forms is generally very reliable, both within and between
environments, Perl apparently excepted.

Not to say that the numbers themselves represent precise quantities, but
that they can be reliably converted and compared to each other.

···

--
Paul Lutus
http://www.arachnoid.com

I understand what you're trying to say, but 'rational' and 'irrational' are the wrong terms. 0.2 = 2/10, therefore it's a rational number (it can be expressed exactly as a ratio), but it can't be represented exactly as a base 2 floating-point number. Whether a number is rational (like 0.2) or irrational (like sqrt(3)) is a basic mathematical property of the number; it has nothing to do with how it's represented.

TomP

···

On Sep 30, 2006, at 2:21 PM, David Vallner wrote:

Your example works because integers are rational IEEE floating point
numbers. Problems arise when you use a number that's a rational decimal
number, but an irrational IEEE binary floating point one. Those aren't
precise no matter what storage size you use.