Почему я получаю разные ответы, когда использую math.fmod и только оператор мода? (для целых чисел) - PullRequest
0 голосов
/ 07 августа 2020

Я пишу следующий код, чтобы найти максимальный подмассив продукта:

def ans(arr, n):
    M = 1000000007
    cur_max = cur_min = ans = arr[0] % M
    for i in range(1, n):
        tmp = cur_max
        cur_max = max(arr[i], cur_min * arr[i]% M, cur_max * arr[i] % M)
        cur_min = min(arr[i], cur_min * arr[i] % M, tmp * arr[i] % M)
        ans = max(ans, cur_max)
    return ans % M

Когда я использую его в array = [6, -3, -10, 0, 2], я получаю ответ: 999999989
В то время как, когда я меняю его на

from math import *
def ans(arr, n):
    M = 1000000007
    cur_max = cur_min = ans = arr[0]
    for i in range(1, n):
        tmp = cur_max
        cur_max = max(arr[i], int(fmod(cur_min * arr[i], M)), int(fmod(cur_max * arr[i], M)))
        cur_min = min(arr[i], int(fmod(cur_min * arr[i], M)), int(fmod(tmp * arr[i], M)))
        ans = max(ans, cur_max)
    return ans

, я получаю ответ: 180
Единственное изменение, которое я сделал, - это использовать функцию fmod, а затем преобразовать ее в целые числа, а не использовать оператор mod (%). Почему я получаю совершенно разные ответы?

1 Ответ

2 голосов
/ 07 августа 2020

Оператор % и math.fmod не выполняют одну и ту же операцию по модулю. В спецификации c обработка отрицательных чисел отличается:

math.fmod (x, y)

[..] Цель стандарт C состоит в том, что fmod(x, y) точно (математически; с бесконечной точностью) равно x - n*y для некоторого целого числа n, так что результат имеет тот же знак, что и x и величина менее abs(y). Python x % y вместо этого возвращает результат со знаком y и может быть не точно вычислим для аргументов с плавающей запятой. [..]

Двоичная арифметика c операций

[..] Оператор по модулю всегда дает результат с тот же знак, что и его второй операнд (или ноль); [..] Функция math.fmod() вместо [..] возвращает результат, знак которого совпадает со знаком первого аргумента . Какой подход более подходящий, зависит от приложения.

>>> def test_mod(a, b): print('%-op:', a % b, 'fmod:', fmod(a, b))
>>> test_mod(10, 12)
%-op: 10 fmod: 10.0
>>> test_mod(-10, 12)
%-op: 2 fmod: -10.0
>>> test_mod(10, -12)
%-op: -2 fmod: 10.0

Оба варианта ans дадут одинаковый результат для положительных входов:

>>> perc_ans([6, 3, 10, 0, 2], 5)
180
>>> math_ans([6, 3, 10, 0, 2], 5)
180
>>> perc_ans([6, -3, -10, 0, 2], 5)
999999989
>>> math_ans([6, -3, -10, 0, 2], 5)
180
...