Integer division with / - request explanation of behavior

W

Wes Gamble

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
 
V

Vincent Fourmond

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
 
R

Robert Klemme

Paul said:
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
 
E

Eero Saynatkari

--JLiXfqD9/Kt1b+Pq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

Wes Gamble wrote:
=20
=20
Not exactly. The result is expressed in the type of the more precise of t= he
two operands.

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


--JLiXfqD9/Kt1b+Pq
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (FreeBSD)

iD8DBQFFHoiX7Nh7RM4TrhIRAiQLAJ0YGnQXyy0fvrFZFYEq7DvdvuqIlACfVnnL
iBc+wxCB5ts9n4Daxulcp30=
=DcDR
-----END PGP SIGNATURE-----

--JLiXfqD9/Kt1b+Pq--
 
D

David Vallner

--------------enigBE3685E78261E5627E61446A
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

Wes said:
Today I discovered the difference in the meaning of the / (arithmetic=20
divide) method depending on whether it's caller is an integer or a=20
float.
=20
I discovered that I had to cast the calling number explicitly to a floa= t=20
and it seemed totally non-intuitive to me.
=20

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.


--------------enigBE3685E78261E5627E61446A
Content-Type: application/pgp-signature; name="signature.asc"
Content-Description: OpenPGP digital signature
Content-Disposition: attachment; filename="signature.asc"

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (MingW32)

iD8DBQFFHpaEy6MhrS8astoRAkxzAJ9GB5R5mQzlyYBcEoysEbEeNDw/FwCeO921
nqgSqd4cQbfjq+iXwxPhX+I=
=bDDP
-----END PGP SIGNATURE-----

--------------enigBE3685E78261E5627E61446A--
 
W

Wes Gamble

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?
 
M

M. Edward (Ed) Borasky

Paul said:
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".
 
R

Robert Klemme

Paul said:
Robert Klemme wrote:

/ ...


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...
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. :) 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. :) The question is whether one should
rely on the binary <-> text conversion. The best for decimal accuracy
is probably BCD anyway...

Kind regards

robert
 
J

Jeremy Tregunna

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

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

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

M. Edward (Ed) Borasky

Robert said:
Would you mind if I suggest this Ruby Quiz

compute *all* didgits of Pi, if you have less time, just compute the
*last*
digit of Pi.

Easy as pi ... just use the Ruby language "call with continued fraction"
feature.
 
D

David Vallner

--------------enig36EC0771B2612EAB387A253F
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

Jeremy said:
=20
Not on all platforms. For instance, in Ocaml, it's true:
=20
# 2. -. 1. =3D 1.;;
- : bool =3D true
=20

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 =3D 1.0000000000000002
# (2.2 -. 1.2) !=3D 1.0;;
- : bool =3D 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 =3D 0.0
=3D> 0.0
irb(main):002:0> 10000.times {
irb(main):003:1* a +=3D 0.0001
irb(main):004:1> }
=3D> 10000
irb(main):005:0> a
=3D> 0.999999999999906
irb(main):006:0>

David Vallner

[1] http://support.microsoft.com/default.aspx?scid=3Dkb;EN-US;q42980


--------------enig36EC0771B2612EAB387A253F
Content-Type: application/pgp-signature; name="signature.asc"
Content-Description: OpenPGP digital signature
Content-Disposition: attachment; filename="signature.asc"

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (MingW32)

iD8DBQFFHrWly6MhrS8astoRAitAAJwJSZxvTwqKGraKwoxLVnwxIgzbWQCffXCj
rizPem9shLANFmM4J9oOVjg=
=PIfZ
-----END PGP SIGNATURE-----

--------------enig36EC0771B2612EAB387A253F--
 
T

Tom Pollard

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.

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,072
Latest member
trafficcone

Latest Threads

Top