Jump to page: 1 2 3
Thread overview
A division problem
Mar 24, 2014
bearophile
Mar 24, 2014
Daniel Murphy
Mar 24, 2014
bearophile
Mar 24, 2014
Chris Williams
Mar 24, 2014
bearophile
Mar 24, 2014
Abdulhaq
Mar 24, 2014
Don
Mar 24, 2014
Marco Leise
Mar 24, 2014
bearophile
Mar 24, 2014
Temtaime
Mar 24, 2014
bearophile
Mar 24, 2014
Peter Alexander
Mar 24, 2014
H. S. Teoh
Mar 24, 2014
bearophile
Mar 24, 2014
bearophile
Re: Reviewing pull requests (was: A division problem)
Mar 24, 2014
Andrej Mitrovic
Re: Reviewing pull requests
Mar 24, 2014
Brad Roberts
Mar 24, 2014
Brad Roberts
Mar 24, 2014
Walter Bright
Mar 25, 2014
Brad Roberts
Mar 25, 2014
Daniel Murphy
Re: Reviewing pull requests
Mar 24, 2014
bearophile
Mar 24, 2014
Asman01
March 24, 2014
This kind of code sometimes is wrong, because you forget to cast x to double before the division and you lose precision (but here the compiler knows that the result of the division will go inside a double):


void main() {
    int x = 15;
    double y = x / 10;
}

The cause is that unfortunately in D the integer division uses the same operator as the FP division. In Python there is the / and // operators. In OcaML there are the / and /., in Delphi there are the / and div operators, in Ada the two operands need to be of the same type.

Seasoned C/C++/D programmers watch for the types every time they perform a division, to avoid that trap. But less experienced programmers introduce bugs with divisions. Can D help the programmer reduce the frequency of similar bugs? And do we want to?

Bye,
bearophile
March 24, 2014
"bearophile"  wrote in message news:nxfidkglrgkqtxdzgojt@forum.dlang.org... 

> Seasoned C/C++/D programmers watch for the types every time they perform a division, to avoid that trap. But less experienced programmers introduce bugs with divisions. Can D help the programmer reduce the frequency of similar bugs? And do we want to?

Newbies have to realize that integers aren't real numbers eventually.
March 24, 2014
On Monday, 24 March 2014 at 03:55:41 UTC, bearophile wrote:
>                                                        Can D help the programmer reduce the frequency of similar bugs? And do we want to?

When doing math, I always use parentheses and casts to force a single possible outcome of the result, regardless of the order of evaluation and auto-casting. I also always write all my case/break statements as a set of matching pairs before writing any code in a switch, so the idea that something would fall through on accident seems like something that could never happen.

People should have habits like these (and putting constant values on the left side of a comparison), but I suspect that most people would be annoyed at being forced to do it by the compiler, even though if they were aware that this was a "good habit", they'd all start doing it and life would be perfect.
March 24, 2014
On Monday, 24 March 2014 at 03:55:41 UTC, bearophile wrote:
>
> Seasoned C/C++/D programmers watch for the types every time they perform a division, to avoid that trap. But less experienced programmers introduce bugs with divisions. Can D help the programmer reduce the frequency of similar bugs? And do we want to?
>

This is the kind of area where an IDE can shine...

March 24, 2014
On Monday, 24 March 2014 at 03:55:41 UTC, bearophile wrote:
> This kind of code sometimes is wrong, because you forget to cast x to double before the division and you lose precision (but here the compiler knows that the result of the division will go inside a double):
>
>
> void main() {
>     int x = 15;
>     double y = x / 10;
> }
>
> The cause is that unfortunately in D the integer division uses the same operator as the FP division. In Python there is the / and // operators. In OcaML there are the / and /., in Delphi there are the / and div operators, in Ada the two operands need to be of the same type.
>
> Seasoned C/C++/D programmers watch for the types every time they perform a division, to avoid that trap. But less experienced programmers introduce bugs with divisions. Can D help the programmer reduce the frequency of similar bugs? And do we want to?
>
> Bye,
> bearophile

It is indeed a common floating-point bug.

I came up with a solution for this a couple of years ago, never got around to doing a pull request, but it's on the newsgroup somewhere. It's a little extension to the range propagation implementation. You add a boolean flag to the range, which indicates 'a fractional part has been discarded'. This flag gets set whenever you perform an integer division (or integer exponentiation with a negative power), and is cleared whenever there is a cast or a bitwise operation.

Then, disallow implicit casting from integer to floating point whenever the fractional bit is set. Catches all these kinds of bugs, doesn't require any changes to the language.



March 24, 2014
Daniel Murphy:

> Newbies have to realize that integers aren't real numbers eventually.

Of course. But from reviewing plenty of code, I have seen that unfortunately even programmers with some experience once in a while create this bug. Because you have to keep attention to the types of each division usage, and once in a while your attention slips (or perhaps some bugs of this kind are created by successive type changes).

Bye,
bearophile
March 24, 2014
Chris Williams:

> I also always write all my case/break statements as a set of matching pairs before writing any code in a switch, so the idea that something would fall through on accident seems like something that could never happen.

Now D catches most of such implicit case fall-through bugs.


> People should have habits like these (and putting constant values on the left side of a comparison),

void main() {
    int x;
    if (x = 5) {}
}


test.d(3,14): Error: assignment cannot be used as a condition, perhaps == was meant?

Bye,
bearophile
March 24, 2014
Am Mon, 24 Mar 2014 09:51:02 +0000
schrieb "Don" <x@nospam.com>:

> It is indeed a common floating-point bug.
> 
> I came up with a solution for this a couple of years ago, never got around to doing a pull request, but it's on the newsgroup somewhere. It's a little extension to the range propagation implementation. You add a boolean flag to the range, which indicates 'a fractional part has been discarded'. This flag gets set whenever you perform an integer division (or integer exponentiation with a negative power), and is cleared whenever there is a cast or a bitwise operation.
> 
> Then, disallow implicit casting from integer to floating point whenever the fractional bit is set. Catches all these kinds of bugs, doesn't require any changes to the language.

Sounds awesome. Could that also be applied to this as well?:

  mask = 1 << bitNum;

-- 
Marco

March 24, 2014
Don:

> It is indeed a common floating-point bug.

I have opened an ER:
https://d.puremagic.com/issues/show_bug.cgi?id=12452

Bye,
bearophile
March 24, 2014
It requires a little more attention and that's all.
Please, stop creating such "fake" enchantments and go to fix real bugs. Thanks.
« First   ‹ Prev
1 2 3