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

Modulus calculation is not correct. #16

Closed
giorgiofran opened this issue Feb 10, 2017 · 11 comments
Closed

Modulus calculation is not correct. #16

giorgiofran opened this issue Feb 10, 2017 · 11 comments

Comments

@giorgiofran
Copy link

There is a problem with modulus calculation when the dividend and/or the divisor are negative numbers.

I attach a simple test file with a new method mod that could be a possible solution (useful to understand the logic) and a more compact one (mod2).

import 'package:rational/rational.dart';
import 'package:test/test.dart';

Rational mod(Rational one, Rational other) {
  Rational remainder = one.remainder(other);
  if (remainder == new Rational(0)) return remainder;
  if (remainder.isNegative) {
    if (other.isNegative) {
      return remainder;
    }
    return other + remainder;
  }
  if (other.isNegative) return other + remainder;
  return remainder;
}

Rational mod2(Rational one, Rational other) {
  Rational remainder = one.remainder(other);
  if (remainder.signum + other.signum == 0) return other + remainder;
  return remainder;
}

main() {

  test('test Modulus', () {
    expect(new Rational(5) % new Rational(4), equals(new Rational(1)));
    expect(new Rational(-5) % new Rational(4), equals(new Rational(3)));
    expect(new Rational(5) % new Rational(-4), equals(new Rational(-3)));
    expect(new Rational(-5) % new Rational(-4), equals(new Rational(-1)));
    expect(new Rational(4) % new Rational(4), equals(new Rational(0)));
    expect(new Rational(-4) % new Rational(4), equals(new Rational(0)));
    expect(new Rational(4) % new Rational(-4), equals(new Rational(0)));
    expect(new Rational(-4) % new Rational(-4), equals(new Rational(0)));
  });

  test('test new version', () {
    expect(mod(new Rational(5), new Rational(4)), equals(new Rational(1)));
    expect(mod(new Rational(-5), new Rational(4)), equals(new Rational(3)));
    expect(mod(new Rational(5), new Rational(-4)), equals(new Rational(-3)));
    expect(mod(new Rational(-5), new Rational(-4)), equals(new Rational(-1)));
    expect(mod(new Rational(4), new Rational(4)), equals(new Rational(0)));
    expect(mod(new Rational(-4), new Rational(4)), equals(new Rational(0)));
    expect(mod(new Rational(4), new Rational(-4)), equals(new Rational(0)));
    expect(mod(new Rational(-4), new Rational(-4)), equals(new Rational(0)));
  });


  test('test new Version "compact"', () {
    expect(mod2(new Rational(5), new Rational(4)), equals(new Rational(1)));
    expect(mod2(new Rational(-5), new Rational(4)), equals(new Rational(3)));
    expect(mod2(new Rational(5), new Rational(-4)), equals(new Rational(-3)));
    expect(mod2(new Rational(-5), new Rational(-4)), equals(new Rational(-1)));
    expect(mod2(new Rational(4), new Rational(4)), equals(new Rational(0)));
    expect(mod2(new Rational(-4), new Rational(4)), equals(new Rational(0)));
    expect(mod2(new Rational(4), new Rational(-4)), equals(new Rational(0)));
    expect(mod2(new Rational(-4), new Rational(-4)), equals(new Rational(0)));
  });


}
@a14n
Copy link
Owner

a14n commented Feb 10, 2017

I try to provide the same result as Dart VM.

main() {
  print(5 % 4);                                 // 1
  print((-5) % 4);                              // 3
  print(5 % (-4));                              // 1
  print((-5) % (-4));                           // 3
  print(4 % 4);                                 // 0
  print((-4) % 4);                              // 0
  print(4 % (-4));                              // 0
  print((-4) % (-4));                           // 0
  print(new Rational(5) % new Rational(4));     // 1
  print(new Rational(-5) % new Rational(4));    // 3
  print(new Rational(5) % new Rational(-4));    // 1
  print(new Rational(-5) % new Rational(-4));   // 3
  print(new Rational(4) % new Rational(4));     // 0
  print(new Rational(-4) % new Rational(4));    // 4 - incorrect
  print(new Rational(4) % new Rational(-4));    // 0
  print(new Rational(-4) % new Rational(-4));   // 4 - incorrect
}

There are indeed 2 incorrect results but not those you mentioned.

@giorgiofran
Copy link
Author

giorgiofran commented Feb 10, 2017

Also some tests in rational package were wrong.
The following are all the tests, some were correct.

expect(mod(new Rational(2), new Rational(1)), equals(new Rational(0)));
  expect(mod(new Rational(0), new Rational(1)), equals(new Rational(0)));
  expect(mod(new Rational(89, 10), new Rational(11, 10)), equals(new Rational(1, 10)));
  expect(mod(new Rational(-12, 10), new Rational(5, 10)), equals(new Rational(3, 10)));
  expect(mod(new Rational(-12, 10), new Rational(-5, 10)), equals(new Rational(-2, 10)));

@giorgiofran
Copy link
Author

Not all the cases in my original post were wrong.
As far as I Know the correct results should be:
5 mod 4 = 1
-5 mod 4 = 3
5 mod -4 = -3
-5 mod -4 = -1
4 mod 4 = 0
-4 mod 4 = 0
4 mod -4 = 0
-4 mod -4 = 0

@giorgiofran
Copy link
Author

Effectively, the VM results are wrong (at least when the result should be negative) ... , they are different also from Javascript (also these are wrong :-( ).
I gave a look on wikipedia and every language has its own way of calculating modulus...
Anyway, I believe that the right one is the one I suggested you.

@a14n
Copy link
Owner

a14n commented Feb 10, 2017

As I said above

I try to provide the same result as Dart VM

On the VM:

  print(5 % (-4));                              // 1
  print((-5) % (-4));                           // 3

So I can not change these results unless the VM results are changed.

@zoechi
Copy link

zoechi commented Feb 10, 2017

Might be related to dart-lang/sdk#28408 (comment)

@a14n
Copy link
Owner

a14n commented Feb 10, 2017

See also dart-lang/sdk#493

@giorgiofran
Copy link
Author

giorgiofran commented Feb 13, 2017

Based on wikipedia, both the calculation I proposed and the VM one are correct.
There is not an unique way of calculating the modulus.
So, the only problem to be fixed is when the remainder is zero.

@a14n
Copy link
Owner

a14n commented Feb 19, 2017

Fixed in version 0.1.10.

@a14n a14n closed this as completed Feb 19, 2017
@a14n a14n reopened this Feb 19, 2017
@a14n
Copy link
Owner

a14n commented Feb 19, 2017

humm, still an issue in browser... :-/

@a14n
Copy link
Owner

a14n commented Feb 19, 2017

fix in browser too in 0.1.10+1

@a14n a14n closed this as completed Feb 19, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants