[Issue 12452] New: To mitigate unwanted integer division precision loss
d-bugmail at puremagic.com
d-bugmail at puremagic.com
Mon Mar 24 07:15:05 PDT 2014
https://d.puremagic.com/issues/show_bug.cgi?id=12452
Summary: To mitigate unwanted integer division precision loss
Product: D
Version: D2
Platform: All
OS/Version: All
Status: NEW
Severity: enhancement
Priority: P2
Component: DMD
AssignedTo: nobody at puremagic.com
ReportedBy: bearophile_hugs at eml.cc
--- Comment #0 from bearophile_hugs at eml.cc 2014-03-24 07:14:56 PDT ---
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.
- - - - - - - - - - - -
--
Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
More information about the Digitalmars-d-bugs
mailing list