kzen.dev
  • Вопросы
  • Метки
  • Пользователи
Оповещения
Вознаграждения
Регистрация
После регистрации, сможете получать уведомления об ответах и комментариях на Ваши вопросы.
Вход
Если у Вас уже есть аккаунт, войдите чтобы проверить новые уведомления.
Тут будут вознаграждения за добавленные вопросы, ответы и комментарий.
Дополнительно
Источник
Редактировать
Анонимный пользователь
Вопрос

Мода на отрицательные числа плавит мой мозг

Я пытаюсь модифицировать целое число для получения позиции в массиве, чтобы оно обходилось по кругу. Выполнение i % arrayLength отлично работает для положительных чисел, но для отрицательных все идет не так.

 4 % 3 == 1
 3 % 3 == 0
 2 % 3 == 2
 1 % 3 == 1
 0 % 3 == 0
-1 % 3 == -1
-2 % 3 == -2
-3 % 3 == 0
-4 % 3 == -1

поэтому мне нужна реализация

int GetArrayIndex(int i, int arrayLength)

такая, чтобы

GetArrayIndex( 4, 3) == 1
GetArrayIndex( 3, 3) == 0
GetArrayIndex( 2, 3) == 2
GetArrayIndex( 1, 3) == 1
GetArrayIndex( 0, 3) == 0
GetArrayIndex(-1, 3) == 2
GetArrayIndex(-2, 3) == 1
GetArrayIndex(-3, 3) == 0
GetArrayIndex(-4, 3) == 2

Я'делал это раньше, но по какой-то причине это'плавит мой мозг сегодня :(

174 2009-07-04T20:22:43+00:00 11
Colonel Panic
Colonel Panic
Редактировал вопрос 7-го мая 2015 в 2:52
Программирование
c#
math
modulo
 ShreevatsaR
ShreevatsaR
4-го июля 2009 в 8:35
2009-07-04T20:35:50+00:00
Дополнительно
Источник
Редактировать
#9228797

Я всегда использую свою собственную функцию mod, определенную как

int mod(int x, int m) {
    return (x%m + m)%m;
}

Конечно, если вас беспокоит наличие двух вызовов операции модуляции, вы можете записать это как

int mod(int x, int m) {
    int r = x%m;
    return r<0 ? r+m : r;
}

или другие варианты.

Это работает потому, что "x%m" всегда находится в диапазоне [-m+1, m-1]. Поэтому, если он отрицательный, то добавление к нему m переведет его в положительный диапазон без изменения его значения по модулю m.

 ShreevatsaR
ShreevatsaR
Редактировал ответ 9-го января 2013 в 4:22
263
0
Хотите что-то узнать? Задавайте Ваш вопрос на нашем сайте
ru.kzen.dev
Петър Петров
Петър Петров
19-го июня 2011 в 4:07
2011-06-19T04:07:56+00:00
Дополнительно
Источник
Редактировать
#9228798

Обратите внимание, что оператор % в C# и C++'на самом деле НЕ является модулем, это остаток. Формула для модуля, которая вам нужна, в вашем случае такова:

float nfmod(float a,float b)
{
    return a - b * floor(a / b);
}

Вам придется перекодировать это в C# (или C++), но именно так вы получите модулор, а не остаток.

Петър Петров
Петър Петров
Редактировал ответ 14-го февраля 2013 в 6:44
74
0
Хотите что-то узнать? Задавайте Ваш вопрос на нашем сайте
ru.kzen.dev
Evgeni Sergeev
Evgeni Sergeev
22-го апреля 2014 в 8:27
2014-04-22T08:27:50+00:00
Дополнительно
Источник
Редактировать
#9228802

Однострочный реализации с помощью % только один раз:

int mod(int k, int n) {  return ((k %= n) < 0) ? k+n : k;  }
13
0
Abin Mathew
Abin Mathew
29-го октября 2013 в 10:32
2013-10-29T10:32:24+00:00
Дополнительно
Источник
Редактировать
#9228800

При добавлении какого-то понимания.

По Евклидово определение Результатом мод должен быть всегда положительным.

Экс:

 int n = 5;
 int x = -3;

 int mod(int n, int x)
 {
     return ((n%x)+x)%x;
 }

Выход:

 -1
Jeff B
Jeff B
Редактировал ответ 2-го октября 2015 в 9:39
6
0
Хотите что-то узнать? Задавайте Ваш вопрос на нашем сайте
ru.kzen.dev
 dcastro
dcastro
4-го января 2014 в 6:08
2014-01-04T18:08:44+00:00
Дополнительно
Источник
Редактировать
#9228801

ShreevatsaR'ы ответьте выиграл't работа для всех случаев, даже если добавить "если(м в<0) м=-м; - то", Если вам приходится за негативное дивидендов/делителей.

Например, мод -12 -10 будет 8, и он должен быть -2.

Следующая реализация будет работать для обоих положительных и отрицательных дивидендов / делители и согласуется с другими реализациями (а именно, Ява, питон, Руби, Скала, схемы, скрипты и Google'калькулятор ы):

internal static class IntExtensions
{
    internal static int Mod(this int a, int n)
    {
        if (n == 0)
            throw new ArgumentOutOfRangeException("n", "(a mod 0) is undefined.");

        //puts a in the [-n+1, n-1] range using the remainder operator
        int remainder = a%n;

        //if the remainder is less than zero, add n to put it in the [0, n-1] range if n is positive
        //if the remainder is greater than zero, add n to put it in the [n-1, 0] range if n is negative
        if ((n > 0 && remainder < 0) ||
            (n < 0 && remainder > 0))
            return remainder + n;
        return remainder;
    }
}

Тестов с использованием в xUnit:

    [Theory]
    [PropertyData("GetTestData")]
    public void Mod_ReturnsCorrectModulo(int dividend, int divisor, int expectedMod)
    {
        Assert.Equal(expectedMod, dividend.Mod(divisor));
    }

    [Fact]
    public void Mod_ThrowsException_IfDivisorIsZero()
    {
        Assert.Throws<ArgumentOutOfRangeException>(() => 1.Mod(0));
    }

    public static IEnumerable<object[]> GetTestData
    {
        get
        {
            yield return new object[] {1, 1, 0};
            yield return new object[] {0, 1, 0};
            yield return new object[] {2, 10, 2};
            yield return new object[] {12, 10, 2};
            yield return new object[] {22, 10, 2};
            yield return new object[] {-2, 10, 8};
            yield return new object[] {-12, 10, 8};
            yield return new object[] {-22, 10, 8};
            yield return new object[] { 2, -10, -8 };
            yield return new object[] { 12, -10, -8 };
            yield return new object[] { 22, -10, -8 };
            yield return new object[] { -2, -10, -2 };
            yield return new object[] { -12, -10, -2 };
            yield return new object[] { -22, -10, -2 };
        }
    }
 dcastro
dcastro
Редактировал ответ 7-го января 2014 в 1:38
5
0
 starblue
starblue
4-го июля 2009 в 8:31
2009-07-04T20:31:52+00:00
Дополнительно
Источник
Редактировать
#9228796

Просто добавьте ваш модуль (arrayLength) к отрицательному результату %, и все будет в порядке.

4
0
Хотите что-то узнать? Задавайте Ваш вопрос на нашем сайте
ru.kzen.dev
Markus Cozowicz
Markus Cozowicz
31-го июля 2015 в 12:29
2015-07-31T00:29:20+00:00
Дополнительно
Источник
Редактировать
#9228803

Для большей производительности курсе девс

uint wrap(int k, int n) ((uint)k)%n

Сравнение производительности

Modulo: 00:00:07.2661827 ((n%x)+x)%x)
Cast:   00:00:03.2202334 ((uint)k)%n
If:     00:00:13.5378989 ((k %= n) < 0) ? k+n : k

Что касается стоимости выполнения отданных на uint посмотреть здесь

4
0
 lilo0
lilo0
25-го июня 2018 в 7:49
2018-06-25T07:49:53+00:00
Дополнительно
Источник
Редактировать
#9228804

Сравнивая две главные ответы

(x%m + m)%m;

и

int r = x%m;
return r<0 ? r+m : r;

На самом деле никто не упомянул о том, что первый может бросить для себя исключение overflowexception при второй выиграл'т. Что еще хуже, с непроверенными контекста по умолчанию, первый ответ может возвращать неправильный ответ (см. мод(инт.Максвеллову - 1, инт.Максвеллову)` например). Так что второй ответ не только кажется быстрее, но и правильнее.

 Jesse
Jesse
Редактировал ответ 25-го июня 2018 в 8:30
4
0
Хотите что-то узнать? Задавайте Ваш вопрос на нашем сайте
ru.kzen.dev
 RenniePet
RenniePet
15-го апреля 2013 в 7:12
2013-04-15T19:12:25+00:00
Дополнительно
Источник
Редактировать
#9228799

Мне нравится трюк представлен Петр н Льюис на этой теме: "Если N имеет ограниченный спектр, то вы можете получить желаемый результат, просто добавив известная постоянным кратным [делитель], что превышает абсолютное значение минимума.&и"

Так что если у меня есть значение д То есть в градусах и я хочу взять

d % 180f

и я хочу избежать проблем, если д отрицательное, то вместо того, чтобы просто сделать это:

(d + 720f) % 180f

Это предполагает, что хотя Д может быть отрицательным, известно, что он никогда не будет больше негатива, чем -720.

 Community
Community
Редактировал ответ 23-го мая 2017 в 11:54
2
0
 fahd
fahd
21-го сентября 2019 в 11:23
2019-09-21T11:23:08+00:00
Дополнительно
Источник
Редактировать
#9228806

Я заметил одну вещь. Это дает только положительные числа в Python ` печать 4%3 печать 3%3 печать 3%3 печать 2%3 печати 1%3 печать 0%3 выведите -1%3 печать -2%3 печать -3%3 печать -4%3

  • это дал мне 1 0 0 2 1 0 2 1 0 2 Но в C, это дает ответы @gormenghastly
#include<stdio.h>

int main()
{
printf("\n %d",3 % 3);
printf("\n %d",4 % 3);
printf("\n %d",3 % 3);
printf("\n %d",2 % 3);
printf("\n %d",1 % 3); 
printf("\n %d", 0 % 3);
printf("\n %d",-1 % 3);
printf("\n %d",-2 % 3);
printf("\n %d",-3 % 3);
printf("\n %d",-4 % 3);

return 0;
}

Я делал определение % от того, что я мог видеть из вывода в Python, но теперь я тоже в замешательстве

0
0
Хотите что-то узнать? Задавайте Ваш вопрос на нашем сайте
ru.kzen.dev
Aaron Franke
Aaron Franke
24-го января 2019 в 3:05
2019-01-24T03:05:09+00:00
Дополнительно
Источник
Редактировать
#9228805

Все ответы здесь отлично работают если делитель положителен, но это's не совсем полным. Вот моя реализация, которая всегда возвращает на интервале `[0, в), такую, что знак на выходе совпадает со знаком делителя, позволяющих отрицательные делители в качестве конечной точки для выходной диапазон.

PosMod(5, 3) возвращает 2 PosMod(-5, 3) возвращает 1 PosMod(5, -3) возвращает -1 PosMod(-5, -3) возвращает -2

    /// <summary>
    /// Performs a canonical Modulus operation, where the output is on the range [0, b).
    /// </summary>
    public static real_t PosMod(real_t a, real_t b)
    {
        real_t c = a % b;
        if ((c < 0 && b > 0) || (c > 0 && b < 0)) 
        {
            c += b;
        }
        return c;
    }

(где real_t может быть любой тип номера)

0
0
Похожие сообщества 20
Physics.Math.Code
Physics.Math.Code
7 218 пользователей
VK: vk.com/physics_math Библиотека: @physics_lib Заметки репетитора: @mentor_it Канал по безопасности: @hack_theory Советские учебные фильмы: @maths_lib YouTube: youtube.com/c/PhysicsMathCode Помощь в решении: vk.com/itmentor Админ: @physicist_i
Открыть telegram
Microsoft Stack Jobs
Microsoft Stack Jobs
2 400 пользователей
Work & freelance only Microsoft Stack. Feed https://t.me/Microsoftstackjobsfeed Чат про F#: @Fsharp_chat Чат про C#: @CSharpChat Чат про Xamarin: @xamarin_russia Чат общения:@dotnettalks
Открыть telegram
С#
С#
2 329 пользователей
Стараемся не флудить. Пишем по делу. Правила: https://t.me/professorweb/430450 Для флуда @svoboda_obsh
Открыть telegram
pro.algorithms
pro.algorithms
2 195 пользователей
Группа по обсуждению алгоритмов, разных архитектурных решений, паттернов проектирования и прикладной математики. Не допускается флуд не по теме, спам, оффтоп и реклама. Простые вопросы: https://t.me/joinchat/AAAAAEHb2qHizHNLpTX0pA Участник @ProDOT
Открыть telegram
CODE BLOG / C#
CODE BLOG / C#
1 765 пользователей
Чат для .NET разработчиков и C# программистов. По всем вопросам: @shwanoff Youtube-канал: https://youtube.com/codeblog Основной канал: @codeblog Вконтакте: https://vk.com/codeblog Правила: https://t.me/codeblog_csharp/246972 Вакансии по тегу #work
Открыть telegram
var chat = new Chat();
var chat = new Chat();
1 626 пользователей
Обсуждение .NET / C# / F# Обсуждение Azure — @azurechat Прочие обсуждения – https://t.me/+zwxI91RGG6s2YzAy
Открыть telegram
Добавить вопрос
Категории
Все
Технологий
Культура / Отдых
Жизнь / Искусство
Наука
Профессии
Бизнес
Пользователи
Все
Новые
Популярные
1
Александр Македонский
Зарегистрирован 6 дней назад
2
Andrei Kalinin
Зарегистрирован 3 недели назад
3
Koroleva Ego
Зарегистрирован 1 месяц назад
4
Star Lenon
Зарегистрирован 1 месяц назад
5
Данил Жевнеров
Зарегистрирован 2 месяца назад
Хотите что-то узнать? Задавайте Ваш вопрос на нашем сайте
ru.kzen.dev
ID
JA
KO
RO
RU
© kzen.dev 2023
Источник
stackoverflow.com
под лицензией cc by-sa 3.0 с атрибуцией