digitalmars.D.learn - std.math.round() - doc bug?
- Stefan Zobel (14/14) Sep 28 2005 DMD 0.133 (Win XP)
- Don Clugston (13/33) Sep 29 2005 It's definitely a doc bug.
- Stefan Zobel (7/40) Sep 29 2005 Thanks for the clarification Don.
- Don Clugston (29/80) Sep 29 2005 There are four rounding modes in IEEE hardware -- nearest, floor, ceil,
- Stefan Zobel (10/66) Sep 29 2005 Don, thank you for the exemplification. However, I don't understand what
DMD 0.133 (Win XP) The documentation for "real round(real x)" says: In reality, it seems to round the "halfway cases" (fractional part = 0.5) away from zero. Considering that round() delegates to std.c.math.roundl() that's not surprising (AFAIK, roundl() is defined to round "away from zero"). It appears that I have to use "real nearbyint(real x)" to achieve the desired "round to the even integer" behavior? I'm by no means an expert in this matter. Can anyone confirm that this is a doc bug? Best regards, Stefan
Sep 28 2005
Stefan Zobel wrote:DMD 0.133 (Win XP) The documentation for "real round(real x)" says: In reality, it seems to round the "halfway cases" (fractional part = 0.5) away from zero. Considering that round() delegates to std.c.math.roundl() that's not surprising (AFAIK, roundl() is defined to round "away from zero"). It appears that I have to use "real nearbyint(real x)" to achieve the desired "round to the even integer" behavior? I'm by no means an expert in this matter. Can anyone confirm that this is a doc bug? Best regards, StefanIt's definitely a doc bug. Here's the behaviour of the existing functions: round() --- rounds away from zero trunc() --- rounds towards zero floor() --- rounds towards negative infinity ceil() --- rounds towards positive infinity nearbyint() --- round to even (use current rounding mode) rint() --- round to even (use current rounding mode) This exactly matches the C99 behaviour. But it seems that there is no way to ensure round-to-even if the current rounding mode is changed. I think that's a deficiency in C that D should rectify. -Don
Sep 29 2005
In article <dhg7cp$1m8d$1 digitaldaemon.com>, Don Clugston says...Stefan Zobel wrote:Thanks for the clarification Don. BTW, how can the current rounding mode be changed? Other rounding modes are "towards negative infinity" and "towards positive infinity" (converting rint() to floor() / ceil()), right? Thanks, StefanDMD 0.133 (Win XP) The documentation for "real round(real x)" says: In reality, it seems to round the "halfway cases" (fractional part = 0.5) away from zero. Considering that round() delegates to std.c.math.roundl() that's not surprising (AFAIK, roundl() is defined to round "away from zero"). It appears that I have to use "real nearbyint(real x)" to achieve the desired "round to the even integer" behavior? I'm by no means an expert in this matter. Can anyone confirm that this is a doc bug? Best regards, StefanIt's definitely a doc bug. Here's the behaviour of the existing functions: round() --- rounds away from zero trunc() --- rounds towards zero floor() --- rounds towards negative infinity ceil() --- rounds towards positive infinity nearbyint() --- round to even (use current rounding mode) rint() --- round to even (use current rounding mode) This exactly matches the C99 behaviour. But it seems that there is no way to ensure round-to-even if the current rounding mode is changed. I think that's a deficiency in C that D should rectify. -Don
Sep 29 2005
Stefan Zobel wrote:In article <dhg7cp$1m8d$1 digitaldaemon.com>, Don Clugston says...There are four rounding modes in IEEE hardware -- nearest, floor, ceil, and trunc(). The round() function in C99 ("high school rounding") is not supported by the hardware, so it's significantly slower. I think it's ridiculous that the most accurate mode is not supported by C99. I also note that in D, cast(int)(x) uses trunc(), following the (stupid and slow) C behaviour. float.html describes how to change the rounding mode. It currently says "[blah, blah, blah]". In a post in dm.D yesterday, I asked Walter what his plans are. He doesn't yet have any. In C, depending on the compiler, it's often done in a user-hostile way with _control87(). Less readable and less portable than asm. C99 has fegetround() and fesetround() in fenv.h. A more D-like alternative might be with properties; something like: if (real.rounding != roundfloor) { typeof(real.rounding) oldmode = real.rounding; real.rounding = roundeven; real.rounding = oldmode; } but at present, all properties for built-in types are read-only. I don't know if writable types would be a problem. Rationale: the rounding mode behaves as if it is a static variable which applies to every floating-point type. Ditto for precision. Downside: it applies to every floating point type, including cfloat and idouble, which in D are not derived from real. I haven't worked out how exceptions could work with properties, though. Do you have any opinions/ideas on any of this? -Don.Stefan Zobel wrote:Thanks for the clarification Don. BTW, how can the current rounding mode be changed? Other rounding modes are "towards negative infinity" and "towards positive infinity" (converting rint() to floor() / ceil()), right? Thanks, StefanDMD 0.133 (Win XP) The documentation for "real round(real x)" says: In reality, it seems to round the "halfway cases" (fractional part = 0.5) away from zero. Considering that round() delegates to std.c.math.roundl() that's not surprising (AFAIK, roundl() is defined to round "away from zero"). It appears that I have to use "real nearbyint(real x)" to achieve the desired "round to the even integer" behavior? I'm by no means an expert in this matter. Can anyone confirm that this is a doc bug? Best regards, StefanIt's definitely a doc bug. Here's the behaviour of the existing functions: round() --- rounds away from zero trunc() --- rounds towards zero floor() --- rounds towards negative infinity ceil() --- rounds towards positive infinity nearbyint() --- round to even (use current rounding mode) rint() --- round to even (use current rounding mode) This exactly matches the C99 behaviour. But it seems that there is no way to ensure round-to-even if the current rounding mode is changed. I think that's a deficiency in C that D should rectify. -Don
Sep 29 2005
In article <dhgqgm$2ajg$1 digitaldaemon.com>, Don Clugston says...Stefan Zobel wrote:Don, thank you for the exemplification. However, I don't understand what your "most accurate" mode is (nearest?). And slightly OT: Why wouldn't it be supported by C99? I'd assume that nearbyint/rint take advantage of CPU instructions, or are they missing from the C99 standard?In article <dhg7cp$1m8d$1 digitaldaemon.com>, Don Clugston says...There are four rounding modes in IEEE hardware -- nearest, floor, ceil, and trunc(). The round() function in C99 ("high school rounding") is not supported by the hardware, so it's significantly slower. I think it's ridiculous that the most accurate mode is not supported by C99.It's definitely a doc bug. Here's the behaviour of the existing functions: round() --- rounds away from zero trunc() --- rounds towards zero floor() --- rounds towards negative infinity ceil() --- rounds towards positive infinity nearbyint() --- round to even (use current rounding mode) rint() --- round to even (use current rounding mode) This exactly matches the C99 behaviour. But it seems that there is no way to ensure round-to-even if the current rounding mode is changed. I think that's a deficiency in C that D should rectify. -DonThanks for the clarification Don. BTW, how can the current rounding mode be changed? Other rounding modes are "towards negative infinity" and "towards positive infinity" (converting rint() to floor() / ceil()), right? Thanks, StefanI also note that in D, cast(int)(x) uses trunc(), following the (stupid and slow) C behaviour. float.html describes how to change the rounding mode. It currently says "[blah, blah, blah]". In a post in dm.D yesterday, I asked Walter what his plans are. He doesn't yet have any.Ah, I see.In C, depending on the compiler, it's often done in a user-hostile way with _control87(). Less readable and less portable than asm. C99 has fegetround() and fesetround() in fenv.h. A more D-like alternative might be with properties; something like: if (real.rounding != roundfloor) { typeof(real.rounding) oldmode = real.rounding; real.rounding = roundeven; real.rounding = oldmode; } but at present, all properties for built-in types are read-only. I don't know if writable types would be a problem. Rationale: the rounding mode behaves as if it is a static variable which applies to every floating-point type. Ditto for precision. Downside: it applies to every floating point type, including cfloat and idouble, which in D are not derived from real.Personally, I'd prefer a library call for that very reason, but that's just me. Best regards, StefanI haven't worked out how exceptions could work with properties, though. Do you have any opinions/ideas on any of this? -Don.
Sep 29 2005