Bug #71368 -1 % 0.5 yields -0.0
Submitted: 14 Jan 2014 2:09 Modified: 12 Nov 2019 22:43
Reporter: Arthur O'Dwyer Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: DML Severity:S2 (Serious)
Version:5.5.31, 5.5.34, 5.5.35, 5.6.15 OS:Any
Assigned to: CPU Architecture:Any

[14 Jan 2014 2:09] Arthur O'Dwyer
Description:
MySQL believes that taking a negative number modulo a positive number (via the % or MOD operator) can yield "negative zero" or "minus zero". This special constant does not compare equal to '-0', but it does compare equal to itself.

How to repeat:
SELECT -1 % 0.5;
 +----------+
 | -1 % 0.5 |
 +----------+
 |     -0.0 |
 +----------+

The right answer is "0.0", not "-0.0".

SELECT -0.0 = (-1 % 0.5);
 +-------------------+
 | -0.0 = (-1 % 0.5) |
 +-------------------+
 |                 0 |
 +-------------------+

The right answer is "1" (TRUE); -0.0 and 0.0 should be synonyms in this context.

Suggested fix:
do_div_mod() contains this code:

  if (mod)
  {
    /* we're calculating N1 % N2.
       The result will have
         frac=max(frac1, frac2), as for subtraction
         intg=intg2
    */
    to->sign=from1->sign;
    to->frac=max(from1->frac, from2->frac);
    frac0=0;
  }

It needs to follow that by the same logic that's duplicated already in a lot of other places (e.g. decimal_mul):

  /* Now we have to check for -0.000 case */
  if (to->sign)
  {
    dec1 *buf= to->buf;
    dec1 *end= to->buf + intg0 + frac0;
    DBUG_ASSERT(buf != end);
    for (;;)
    {
      if (*buf)
        break;
      if (++buf == end)
      {
        /* We got decimal zero */
        decimal_make_zero(to);
        break;
      }
    }
  }

Really, I strongly suggest pulling that logic out into a helper function named something like decimal_avoid_negative_zero() and calling that helper function from all the places where the code is currently duplicated.
[14 Jan 2014 5:49] MySQL Verification Team
Hello Arthur,

Thank you for the bug report. 
Verified as described.

Thanks,
Umesh
[12 Nov 2019 22:43] Roy Lyseng
Posted by developer:
 
Fixed in 5.7