Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

To mitigate unwanted integer division precision loss #18801

Open
dlangBugzillaToGithub opened this issue Mar 24, 2014 · 1 comment
Open

To mitigate unwanted integer division precision loss #18801

dlangBugzillaToGithub opened this issue Mar 24, 2014 · 1 comment

Comments

@dlangBugzillaToGithub
Copy link

bearophile_hugs reported this on 2014-03-24T07:14:56Z

Transferred from https://issues.dlang.org/show_bug.cgi?id=12452

CC List

Description

This kind of code sometimes is wrong, because you forget to cast x to double before the division and you lose precision (note that here the compiler knows that the result of the division will go in a floating point variable):


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, and they often use explicit casts in that kind of code (this uses a recently introduce syntax that avoids the use of a cast()):

double y = double(x) / 10;

But less experienced programmers introduce bugs with divisions. Can D help the programmers reduce the frequency of similar bugs?

- - - - - - - - - - - -

A comment by Daniel Murphy:

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

I have seen that 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).


An example of this possible code found in real code:

Search for "GetTransmission()" in this page:
http://www.viva64.com/en/b/0242/

The possible bug:

int SpectralLMM5Interface::GetTransmission(....,
                                           double& transmission)
{
  ....
  int16_t tr = 0;
  memcpy(&tr, answer + 1, 2);
  tr = ntohs(tr);
  transmission = tr/10;
  ....
}

- - - - - - - - - - - -

Don suggests:

> 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.

- - - - - - - - - - - -
@dlangBugzillaToGithub
Copy link
Author

nick (@ntrel) commented on 2021-05-26T10:02:20Z

> 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.

https://forum.dlang.org/post/hg5291$fas$1@digitalmars.com

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant