digitalmars.D - Promotion rules ... why no float?
- Sai (18/18) Sep 06 2016 Consider this:
- Stefan Koch (3/21) Sep 06 2016 Because implicit conversion to float on every division is bad bad
- Andrea Fontana (3/21) Sep 06 2016 Integer division and modulo are not bugs.
- Jonathan M Davis via Digitalmars-d (17/43) Sep 06 2016 Indeed. There are a lot of situations where they are exactly what you wa...
- Sai (14/14) Sep 06 2016 Thanks for the replies.
- Steven Schveighoffer (3/11) Sep 06 2016 auto c = float(a) / b;
- Daniel Kozak via Digitalmars-d (3/19) Sep 06 2016 another solution is use own function for div operation
- Daniel Kozak via Digitalmars-d (3/16) Sep 06 2016 Because of alias this it works quite well for me in many cases. However
- Andrea Fontana (10/24) Sep 06 2016 Exotic way:
- R (2/16) Sep 07 2016 http://code.dlang.org/packages/fixed ?
- pineapple (5/6) Sep 07 2016 Quoted for emphasis
- Daniel Kozak via Digitalmars-d (8/26) Sep 06 2016 No, it is really important rule. If there will be automatic promotion to...
- deadalnix (5/8) Sep 06 2016 The performance have nothing to do with it. In fact float
- Daniel Kozak via Digitalmars-d (4/12) Sep 06 2016 You are right, on my pc speed is same, but I am remember that there has
- Sai (11/27) Sep 07 2016 I suspected the same, most of the CPUs support fast floating
- Lodovico Giaretta (13/22) Sep 07 2016 x == x/k + x%k
- Lodovico Giaretta (6/7) Sep 07 2016 Of course that was:
- John Colvin (6/11) Sep 07 2016 python3 uses / for floating point division and // for integer. I
- Nick Treleaven (4/20) Sep 07 2016 Personally I agree. A more nuanced solution is filed here:
- Sai (12/24) Sep 07 2016 WOW, I didn't know python 3 fixed this issue, and I just found
- deadalnix (12/16) Sep 07 2016 No. Floating point in binaries are represented as
Consider this: import std.stdio; void main() { byte a = 6, b = 7; auto c = a + b; auto d = a / b; writefln("%s, %s", typeof(c).stringof, c); writefln("%s, %s", typeof(d).stringof, d); } Output : int, 13 int, 0 I really wish d gets promoted to a float. Besides C compatibility, any reason why d got promoted only to int even at the risk of serious bugs and loss of precision? I know I could have typed "auto a = 6.0" instead, but still it feels like an half-baked promotion rules.
Sep 06 2016
On Tuesday, 6 September 2016 at 07:04:24 UTC, Sai wrote:Consider this: import std.stdio; void main() { byte a = 6, b = 7; auto c = a + b; auto d = a / b; writefln("%s, %s", typeof(c).stringof, c); writefln("%s, %s", typeof(d).stringof, d); } Output : int, 13 int, 0 I really wish d gets promoted to a float. Besides C compatibility, any reason why d got promoted only to int even at the risk of serious bugs and loss of precision? I know I could have typed "auto a = 6.0" instead, but still it feels like an half-baked promotion rules.Because implicit conversion to float on every division is bad bad bad.
Sep 06 2016
On Tuesday, 6 September 2016 at 07:04:24 UTC, Sai wrote:Consider this: import std.stdio; void main() { byte a = 6, b = 7; auto c = a + b; auto d = a / b; writefln("%s, %s", typeof(c).stringof, c); writefln("%s, %s", typeof(d).stringof, d); } Output : int, 13 int, 0 I really wish d gets promoted to a float. Besides C compatibility, any reason why d got promoted only to int even at the risk of serious bugs and loss of precision? I know I could have typed "auto a = 6.0" instead, but still it feels like an half-baked promotion rules.Integer division and modulo are not bugs. Andrea
Sep 06 2016
On Tuesday, September 06, 2016 07:26:37 Andrea Fontana via Digitalmars-d wrote:On Tuesday, 6 September 2016 at 07:04:24 UTC, Sai wrote:Indeed. There are a lot of situations where they are exactly what you want. Floating point adds imprecision to calculations that you often want to avoid. Also, if I understand correctly, floating point operations are more expensive that the corresponding integer operations. So, it would be very bad if dividing integers resulted in a floating point value by default. And if you _do_ want a floating point value, then you can cast one of the operands to the floating point type you want, and you'll get floating point arithmetic. Personally, I find that I rarely need floating point values at all. Another thing to take into account is that you don't normally want stuff like arithmetic operations to do type conversion. We already have enough confusion about byte and short being converted to int when you do arithmetic on them. Having other types suddenly start changing depending on the operations involved would just make things worse. - Jonathan M DavisConsider this: import std.stdio; void main() { byte a = 6, b = 7; auto c = a + b; auto d = a / b; writefln("%s, %s", typeof(c).stringof, c); writefln("%s, %s", typeof(d).stringof, d); } Output : int, 13 int, 0 I really wish d gets promoted to a float. Besides C compatibility, any reason why d got promoted only to int even at the risk of serious bugs and loss of precision? I know I could have typed "auto a = 6.0" instead, but still it feels like an half-baked promotion rules.Integer division and modulo are not bugs.
Sep 06 2016
Thanks for the replies. I tend to use a lot of float math (robotics and automation) so I almost always want float output in case of division. And once in a while I bump into this issue. I am wondering what are the best ways to work around it. float c = a / b; // a and b could be integers. Some solutions: float c = cast!float(a) / b; float c = 1f * a / b; Any less verbose ways to do it? Another solution I am thinking is to write a user defined integer type with an overloaded division to return a float instead and use it everywhere in place of integers. I am curious how this will work out.
Sep 06 2016
On 9/6/16 11:00 AM, Sai wrote:Thanks for the replies. I tend to use a lot of float math (robotics and automation) so I almost always want float output in case of division. And once in a while I bump into this issue. I am wondering what are the best ways to work around it. float c = a / b; // a and b could be integers. Some solutions: float c = cast!float(a) / b;auto c = float(a) / b; -Steve
Sep 06 2016
Dne 6.9.2016 v 17:26 Steven Schveighoffer via Digitalmars-d napsal(a):On 9/6/16 11:00 AM, Sai wrote:another solution is use own function for div operation auto c = div(a,b);Thanks for the replies. I tend to use a lot of float math (robotics and automation) so I almost always want float output in case of division. And once in a while I bump into this issue. I am wondering what are the best ways to work around it. float c = a / b; // a and b could be integers. Some solutions: float c = cast!float(a) / b;auto c = float(a) / b; -Steve
Sep 06 2016
Dne 6.9.2016 v 17:00 Sai via Digitalmars-d napsal(a):Thanks for the replies. I tend to use a lot of float math (robotics and automation) so I almost always want float output in case of division. And once in a while I bump into this issue. I am wondering what are the best ways to work around it. float c = a / b; // a and b could be integers. Some solutions: float c = cast!float(a) / b; float c = 1f * a / b; Any less verbose ways to do it? Another solution I am thinking is to write a user defined integer type with an overloaded division to return a float instead and use it everywhere in place of integers. I am curious how this will work out.Because of alias this it works quite well for me in many cases. However one unplesant situation is with method parameters
Sep 06 2016
On Tuesday, 6 September 2016 at 15:00:48 UTC, Sai wrote:Thanks for the replies. I tend to use a lot of float math (robotics and automation) so I almost always want float output in case of division. And once in a while I bump into this issue. I am wondering what are the best ways to work around it. float c = a / b; // a and b could be integers. Some solutions: float c = cast!float(a) / b; float c = 1f * a / b; Any less verbose ways to do it? Another solution I am thinking is to write a user defined integer type with an overloaded division to return a float instead and use it everywhere in place of integers. I am curious how this will work out.Exotic way: import std.stdio; float div(float a, float b) { return a / b; } void main() { auto c = 3.div(4); writeln(c); }
Sep 06 2016
On Tuesday, 6 September 2016 at 15:00:48 UTC, Sai wrote:Thanks for the replies. I tend to use a lot of float math (robotics and automation) so I almost always want float output in case of division. And once in a while I bump into this issue. I am wondering what are the best ways to work around it. float c = a / b; // a and b could be integers. Some solutions: float c = cast!float(a) / b; float c = 1f * a / b; Any less verbose ways to do it? Another solution I am thinking is to write a user defined integer type with an overloaded division to return a float instead and use it everywhere in place of integers. I am curious how this will work out.http://code.dlang.org/packages/fixed ?
Sep 07 2016
On Tuesday, 6 September 2016 at 07:26:37 UTC, Andrea Fontana wrote:Integer division and modulo are not bugs.Quoted for emphasis If you want floating point math, then declare your variables as floats.
Sep 07 2016
Dne 6.9.2016 v 09:04 Sai via Digitalmars-d napsal(a):Consider this: import std.stdio; void main() { byte a = 6, b = 7; auto c = a + b; auto d = a / b; writefln("%s, %s", typeof(c).stringof, c); writefln("%s, %s", typeof(d).stringof, d); } Output : int, 13 int, 0 I really wish d gets promoted to a float. Besides C compatibility, any reason why d got promoted only to int even at the risk of serious bugs and loss of precision? I know I could have typed "auto a = 6.0" instead, but still it feels like an half-baked promotion rules.No, it is really important rule. If there will be automatic promotion to float for auto it will hurt performance in cases when you want int and it will break things. But maybe in below case it could make more sense: float d = a / b; // or it could print a warning because there is a high probability this is an error ok maybe something like linter could be use to find those places
Sep 06 2016
On Tuesday, 6 September 2016 at 07:52:47 UTC, Daniel Kozak wrote:No, it is really important rule. If there will be automatic promotion to float for auto it will hurt performance in cases when you want int and it will break things.The performance have nothing to do with it. In fact float division is way faster than integer division, try it. It is all about correctness. Integer and floating point division have different semantic.
Sep 06 2016
Dne 6.9.2016 v 22:51 deadalnix via Digitalmars-d napsal(a):On Tuesday, 6 September 2016 at 07:52:47 UTC, Daniel Kozak wrote:You are right, on my pc speed is same, but I am remember that there has been some performance problems last time i checked (something about only one FPU on my bulldozer cpu)No, it is really important rule. If there will be automatic promotion to float for auto it will hurt performance in cases when you want int and it will break things.The performance have nothing to do with it. In fact float division is way faster than integer division, try it. It is all about correctness. Integer and floating point division have different semantic.
Sep 06 2016
I suspected the same, most of the CPUs support fast floating point operations anyway (with FPUs), shouldn't take a lot more time than doing integer arithmetic. Unless we are targeting 8bit avr or something similar. And precision argument doesn't seem strong either, since, which is more precise 3/7 = 0 or 0.4285 ? I am not suggesting we change the promotion rules now, most likely never going to happen. But I am trying to find a good rationale for the existing rules and unable to find a good one. On Wednesday, 7 September 2016 at 05:31:08 UTC, Daniel Kozak wrote:Dne 6.9.2016 v 22:51 deadalnix via Digitalmars-d napsal(a):On Tuesday, 6 September 2016 at 07:52:47 UTC, Daniel Kozak wrote:You are right, on my pc speed is same, but I am remember that there has been some performance problems last time i checked (something about only one FPU on my bulldozer cpu)No, it is really important rule. If there will be automatic promotion to float for auto it will hurt performance in cases when you want int and it will break things.The performance have nothing to do with it. In fact float division is way faster than integer division, try it. It is all about correctness. Integer and floating point division have different semantic.
Sep 07 2016
On Wednesday, 7 September 2016 at 14:46:46 UTC, Sai wrote:I suspected the same, most of the CPUs support fast floating point operations anyway (with FPUs), shouldn't take a lot more time than doing integer arithmetic. Unless we are targeting 8bit avr or something similar. And precision argument doesn't seem strong either, since, which is more precise 3/7 = 0 or 0.4285 ? I am not suggesting we change the promotion rules now, most likely never going to happen. But I am trying to find a good rationale for the existing rules and unable to find a good one.x == x/k + x%k The above formula holds in integer arithmetic. It is fundamental in many operations. You cannot achieve the same with floating point calculations. Whenever you do batch jobs, dividing you work into groups (and you don't really want 2.3 groups) and whenever you iterate the digits of a number, implicit floating point conversions can really hurt. I think the current state of affairs is fairly good. Adding implicit conversions would make it worst. What would probably make it better (but can't be changed now) is having two distinct operators, one for integer division and one with implicit floating point conversions.
Sep 07 2016
On Wednesday, 7 September 2016 at 15:09:42 UTC, Lodovico Giaretta wrote:x == x/k + x%kOf course that was: x == (x/k)*k + x%k But ok, you got the idea: going back and forth is lossless, just remember to add the modulus.
Sep 07 2016
On Wednesday, 7 September 2016 at 15:09:42 UTC, Lodovico Giaretta wrote:I think the current state of affairs is fairly good. Adding implicit conversions would make it worst. What would probably make it better (but can't be changed now) is having two distinct operators, one for integer division and one with implicit floating point conversions.python3 uses / for floating point division and // for integer. I really like the distinction, although I would prefer if / was disallowed on integer operands entirely, i.e. 3/2.0 is ok but 3/2 is not, that would be an error and you'd have to do 3 // 2
Sep 07 2016
On Wednesday, 7 September 2016 at 15:15:03 UTC, John Colvin wrote:python3 uses / for floating point division and // for integer. I really like the distinction, although I would prefer if / was disallowed on integer operands entirely, i.e. 3/2.0 is ok but 3/2 is not, that would be an error and you'd have to do 3 // 2Personally I agree. A more nuanced solution is filed here: https://issues.dlang.org/show_bug.cgi?id=12452 At the end of the description, Don is quoted: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.
Sep 07 2016
On Wednesday, 7 September 2016 at 16:04:05 UTC, Nick Treleaven wrote:On Wednesday, 7 September 2016 at 15:15:03 UTC, John Colvin wrote:WOW, I didn't know python 3 fixed this issue, and I just found out that python 2 can also do it by importing from future. I have been using python 2.7 at my work for several years without knowing this and ran into this issue so many times, stupid me. Thanks for the info, I will update my python code asap. (In my defense, I am not a full time programmer). In D though, all solutions seem to add noise at the usage site, template solution with alias this might be the cleanest to retrofit all integers with floating point division. - Saipython3 uses / for floating point division and // for integer. I really like the distinction, although I would prefer if / was disallowed on integer operands entirely, i.e. 3/2.0 is ok but 3/2 is not, that would be an error and you'd have to do 3 // 2Personally I agree. A more nuanced solution is filed here: https://issues.dlang.org/show_bug.cgi?id=12452 At the end of the description, Don is quoted:It is indeed a common floating-point bug. ...
Sep 07 2016
On Wednesday, 7 September 2016 at 14:46:46 UTC, Sai wrote:I suspected the same, most of the CPUs support fast floating point operations anyway (with FPUs), shouldn't take a lot more time than doing integer arithmetic. Unless we are targeting 8bit avr or something similar.No. Floating point in binaries are represented as v = m * 2 ^ e Now: v0 / v1 = (m0 * 2 ^ e0) / (m1 * 2 ^ e1) v0 / v1 = (m0 / m1) * 2 ^ (e0 - e1) ie to do a 32 bits float division, you need to do a 24 bits integer division, while when doing a 32bits integer division you need to do a 32bits integer division (!) The same apply to floating point multiply that are usually faster than integer multiply. In fact, on some machines, multiplying floats is faster than adding them.
Sep 07 2016