Re[6]: Откуда эта лютая любовь к знаковым целым?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 08.05.20 05:30
Оценка:
Здравствуйте, Erop, Вы писали:

E>Натуральные числа -- это и есть целы. Они в целые вложены. То есть, все натуральные являются целыми, во-первых, и все операции над натуральными, результат которых определён, дают тот же результат с целыми (это если про математику говорить)

E>Мало того, целые и натуральные равномощны.

Вместо того, чтобы повторять очевидное, просто объясните, почему понятие натурального числа до сих пор не исчезло из математики, как из физики исчезло понятие эфира.
Re[8]: Откуда эта лютая любовь к знаковым целым?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 08.05.20 05:35
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Для универсальных алгоритмов и контейнеров широкого назначения знаковая адресация вполне допустима. А вот для чего, например, argc в main имеет знаковый тип? В каких случаях он может становиться отрицательным?


Это чисто наследие самых ранних реализаций, не захотели менять тип ради мелочи.
Но то, что int ему нигде не мешает, показательно.
The God is real, unless declared integer.
Re[2]: Откуда эта лютая любовь к знаковым целым?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 08.05.20 05:40
Оценка: 5 (1) +3
Здравствуйте, Erop, Вы писали:

E>Насколько я понял, речь идёт о читабельности кода, в первую очередь


Ну вот я читаю код, и вижу там "int NumberOfElements". Что я должен думать об этой переменной? Судя по названию, она содержит количество элементов чего-либо. Судя по типу, она может принимать отрицательные значения. Как это улучшает читабельность?

Исходно в C не было логического типа, но "для улучшения читабельности" считалось естественным вводить синоним boolean или bool. А для чего, собственно? Чего для этого не хватало в int?

Еще более показательная хрень случилась с массовым использованием signed char для символьных/строковых операций. Когда вышли за пределы ASCII, внезапно оказалось, что для проверки вхождения символа в кодовый интервал нельзя использовать вроде бы естественные сравнения. Хотя это было очевидно с самого начала.
Re[5]: Откуда эта лютая любовь к знаковым целым?
От: Alexander G Украина  
Дата: 08.05.20 05:49
Оценка:
Здравствуйте, netch80, Вы писали:


AG>>(MSVC похоже никуда не идёт, он тупо делает реальное сравнение в обоих случаях a + 1 > a)


N>Ну, похоже, MSVC сильно отстал. Хотя это какого года версия? Они с 2015 кричат про переход на SSA, там многое должно заметно поменяться.


2019.
На godbolt почти свежак:

https://godbolt.org/z/j-oupf

Превью (последний, 1 мая 2020) не лучше

N>>>Что сравнивали-то? Intel рисует (почти) противоположное — для длинного умножения времена одинаковы, а для короткого (которому пофиг на знак) на 1-2 такта меньше (3 вместо до 5).

AG>>Обычное деление достаточно больших чисел int64_t / uint64_t, компиляция MSVC x64, беззнаковые ощутимо быстрее. Нужно воспроизвести?

N>Это уже речь про деление, а перед этим было про умножение


N>Вообще, если настроение, киньте код, я сверю в своих условиях.


#include <atomic>
#include <chrono>
#include <cstdint>
#include <iostream>

template<typename Integer>
Integer MultiplyDivide(Integer number, Integer numerator, Integer denominator)
{
    return number * numerator / denominator;
    // на самом деле _mul128 _div128, ну или _umul128 _udiv128 для беззанковых,
    // но для портабельности между компиляторами пусть так
}

template<typename Integer>
struct Benchmark
{
    // чтобы не выоптимизировались; компиляторы пока ещё не научились оптимизировать атомики
    std::atomic<Integer> number{ 123'456'789 };
    std::atomic<Integer> numerator{ 1'000'000'000 };
    std::atomic<Integer> denominator{ 10'000 };
    std::atomic<Integer> result{ 0 };

    std::chrono::duration<double, std::milli> Run()
    {
        auto start = std::chrono::steady_clock::now();
        for (unsigned i = 0; i != 100'000'000; i++)
        {
            result.store(
                MultiplyDivide<Integer>(
                    number.load(std::memory_order_relaxed),
                    number.load(std::memory_order_relaxed),
                    number.load(std::memory_order_relaxed)),
                std::memory_order_relaxed);
        }
        return std::chrono::steady_clock::now() - start;
    }
};

int main()
{
    for (unsigned i = 0; i != 2; i++)
    {
        std::cout << Benchmark<std::uint64_t>{}.Run().count() << "ms unsinged\n";
        std::cout << Benchmark<std::int64_t>{}.Run().count() << "ms singed\n";
    }
}


1558.57ms unsinged
1633.12ms singed
1548.84ms unsinged
1644.11ms singed
Русский военный корабль идёт ко дну!
Re[5]: Откуда эта лютая любовь к знаковым целым?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 08.05.20 06:07
Оценка:
Здравствуйте, Poopy Joe, Вы писали:

H>>>>Во-вторых, иногда нужно не-валидное значение чего-то, что по смыслу неотрицательно. И для этого я лично использую «-1». И если переменная равна ему, то значит значение невалидное. Такая штука с unsigned не проканает, если не вводить всякие magic digits конечно.

PJ>>>std::optional<uint>
N>>И терять 4-8 байт вместо одного бита ;[
PJ>корретное поведение вместо креша того стоит.

Только при условии, что вы не можете выделить даже одно-единственное значение на признак невалидности. И часто такое бывает?
The God is real, unless declared integer.
Re[13]: Откуда эта лютая любовь к знаковым целым?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 08.05.20 06:17
Оценка:
Здравствуйте, vopl, Вы писали:

N>>>>А, на входе... я тело цикла смотрел, там идентично. Что там на входе делается — обычно, считается, на производительность не влияет — посмотрите какой ужас компилируется при векторизации на входе и выходе основного цикла — и всё равно это считается безвредным

V>>>Мелочь — не считается?
N>>Тут скорее таки да.
V>Кому как. В лабораторной синтетике оно конечно не заметно, все взгляды на тело цикла. А на практике будет какая нибудь вложенная-вложенная-вложенная криптуха или мультимедиа-фильтры или еще чего...

В криптухе, подобных фильтрах и т.п. и так будут вылизывать основные операции, делать развёртку циклов, векторизацию(!), ручное кодирование на ассемблере (см. GMP), и так далее... проблемы одной дополнительной операции на входе в цикл будут уже ничтожны.
И, я смотрю, тут любят godbolt — вот типовой вариант во что превращается вроде бы простой код в таком случае — что тут от одной операции на входе?

N>>А вы доказали, что она не имеет смысла? Нет, вы просто с помощью правила неявной конверсии форсировали компилятору игнорирование проблемы.


V>Не доказал, аксиоматически установил. По (неявной) аксиоматике ТС "end — beg >= 0", исходя из фразы "по смыслу должно быть беззнаковое целое". Вот и скармливаю ему беззнаковые, явно говорю ему, "беззнаковые, кольцо", "в операторе сравнения делай расширение до беззнакового, как ты обычно и делаешь".


"Неявная аксиоматика" на внешне неочевидное правило, на котором спотыкается, пока не набьют должное количество шишек, все программисты — это пять
Но авторы новых средств обычно не согласны и придумывают всякие контракты в языках.
The God is real, unless declared integer.
Re[8]: Откуда эта лютая любовь к знаковым целым?
От: vopl Россия  
Дата: 08.05.20 07:59
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, vopl, Вы писали:


V>>Ну, хз. То ли получаются те самые фломастеры, которые разные на вкус и цвет, то ли теперь надо определиться, что за "числа, которые нужны" и почему они без мнимой части, ато вдруг программист будет не только вычитание делать, но еще и корни начнет извлекать..


E>Тут есть тонкость. Целые вложены в вещественные (в том смысле, что если результат какой-то операции на целых определён, то он такой же и на вещественных) вещественные -- в комплексные. Целые, кстати, ещё вложены и в гаусовы, которые тоже вложены в комплексные. Но гаусовы числа у программистов почему-то не особо в чести


E>В области тех моделей чисел, что доступны в С, всё не так хорошо, потому, что они вложениями не являются, хотя в чём-то всё равны близки к идеалу.


E>А вот модули по вычету они вложением в целые, вещественные или комплексные не являются. Они даже не являются вложениями друг в друга.

E>То есть, например, корректно вычисленная сумма int32_t будет та же и для int64_t. А вот с uint32_t и uint64_t такая фигня уже не проходит

Что за "числа, которые нужны" — это, пожалуй, был хороший вопрос

Что за софистика приведена выше? Вот еще тезисы в таком же ключе:
1. целые int32_t не являются подмножеством математических целых, так как они закольцованы
2. вещественные float/double/... не являются подмножеством действительных математических целых, так как...
3. int32 не являются вложением int64 так как кольца у них разные (не в c++, в x86 например), формулировка "корректно вычисленная сумма" неуместна ибо является спецификой для int32.
4. вещественные float не являются вложением double...
5. ...

Да это всё — разные модели. Они все "не являются". Оригинальный замес ТС был про то, что "в некоторых ситуациях даны все условия чтобы использовать беззнаковые, почему вместо них все продолжают использовать знаковые?". Кольца, переполнения, другие ужасы — это все выходит за рамки оригинального вопроса. Да и ладно что беззнаковые — кольца. В оригинальных условиях это никогда не выстрелит.

Вот ты говоришь "корректно вычисленная сумма int32_t будет...". Что за "корректность" такая, кто сказал что должны применяться именно эти твои правила "корректности"? Правила этой темы задал ТС в своем стартовом сообщении. А ты тут придумываешь _другие_ правила. Конечно, по этим другим правилам получается что то другое. Те самые "числа, которые НЕ нужны".
Re[8]: Откуда эта лютая любовь к знаковым целым?
От: vopl Россия  
Дата: 08.05.20 08:02
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, vopl, Вы писали:


V>>

V>>На мой взгляд в конструкции "Надо нумеровать члены последовательности" + "целое число из диапазона [INT_MIN, INT_MAX]" + "кольцо модулей по вычетам какой-то неизвестной степени двойки" лишнее-то, как раз кольцо...



V>>так надо было думать если закольцованность не при чем?


E>Тип -- это не только значения, но и операции же. Скажем для всех чисел (и тех и других) определены ++ и --.

E>При этом для беззнаковых глюки (неопределённое поведение или там перескок с одной границы диапазона на другую или насыщене, как ты там доопределить хочешь) будет происходить в дали от реально используемых значений индексов. Если индекс попал с такую область, где можно заметить, что это только отрезок целых, а не все целые, как в python, например, уже сам по себе подозрительный для индекса.
E>А вот с unsigned это не так.
E>В любом случае, сейчас int не "зациклен", в отличии от. Так что сейчас выбор ещё более определён...

Похоже, мы говорим на разных языках и о разных вещах, предлагаю не продолжать
Re[9]: Откуда эта лютая любовь к знаковым целым?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 08.05.20 08:26
Оценка:
Здравствуйте, netch80, Вы писали:

ЕМ>>для чего, например, argc в main имеет знаковый тип? В каких случаях он может становиться отрицательным?


N>Это чисто наследие самых ранних реализаций, не захотели менять тип ради мелочи.


Значения времени/даты в tm, значение смещение в va_list (и приведение результата sizeof к int в va_arg) и подобное — тоже "чисто наследие"?
Re[10]: Откуда эта лютая любовь к знаковым целым?
От: Nuzhny Россия https://github.com/Nuzhny007
Дата: 08.05.20 09:27
Оценка: 1 (1) +1
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Значения времени/даты в tm, значение смещение в va_list (и приведение результата sizeof к int в va_arg) и подобное — тоже "чисто наследие"?


Тот факт, что time_t — это знаковый int64, очень мудрое решение. Потому что для времени операция вычитания определена и законна: насколько раньше/позже? Так мы сейчас вообще придём к тому, что знаковые не нужны и их надо эмулировать через беззнаковые и отдельно хранить флаг — направление на числовой оси. Ох, чёрт! Мы же получим знаковые
Re[11]: Откуда эта лютая любовь к знаковым целым?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 08.05.20 09:37
Оценка:
Здравствуйте, Nuzhny, Вы писали:

N>Тот факт, что time_t — это знаковый int64


Я говорил не о time_t, а о struct tm.

N>очень мудрое решение. Потому что для времени операция вычитания определена и законна: насколько раньше/позже?


Что-то Вас совсем не в ту степь понесло. Операция вычитания для дней в месяце, лет в эпохе не определена? Или незаконна? Каким образом школьники до изучения отрицательных чисел ухитряются определять, что 2020-й год — это на пять лет позже 2015-го, а 1970-й — на тридцать лет раньше 2000-го?

N>Так мы сейчас вообще придём к тому, что знаковые не нужны и их надо эмулировать через беззнаковые и отдельно хранить флаг — направление на числовой оси.


Если отвечать в точности на то, что написано — не придем.
Re[12]: Откуда эта лютая любовь к знаковым целым?
От: Nuzhny Россия https://github.com/Nuzhny007
Дата: 08.05.20 09:43
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Что-то Вас совсем не в ту степь понесло. Операция вычитания для дней в месяце, лет в эпохе не определена? Или незаконна? Каким образом школьники до изучения отрицательных чисел ухитряются определять, что 2020-й год — это на пять лет позже 2015-го, а 1970-й — на тридцать лет раньше 2000-го?


Потому что они в голове сперва выполняют проверку на больше/меньше и уже потом из большего вычитают меньшее. С отрицательными числами такие проверки часто можно опускать в принципе.
Re[13]: Откуда эта лютая любовь к знаковым целым?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 08.05.20 10:00
Оценка:
Здравствуйте, Nuzhny, Вы писали:

N>Потому что они в голове сперва выполняют проверку на больше/меньше и уже потом из большего вычитают меньшее.


Вас это смущает? Меня — ничуть, коли уж человек от рождения оперирует понятиями "до/после", "выше/ниже" и подобными. А если чей-то возраст вдруг оказался больше возраста любого из его биологических родителей, то это вызывает недоумение даже у дикарей, никогда не слыхавших об отрицательных числах.

N>С отрицательными числами такие проверки часто можно опускать в принципе.


В принципе их опустить нельзя — только применить в другом месте и в другом виде. Ну и я правильно понял, что в своем коде Вы предпочитаете писать "if (a — b < 0)" вместо "if (a < b)"?
Re[14]: Откуда эта лютая любовь к знаковым целым?
От: Nuzhny Россия https://github.com/Nuzhny007
Дата: 08.05.20 10:13
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

N>>С отрицательными числами такие проверки часто можно опускать в принципе.

ЕМ>В принципе их опустить нельзя — только применить в другом месте и в другом виде. Ну и я правильно понял, что в своем коде Вы предпочитаете писать "if (a — b < 0)" вместо "if (a < b)"?

Нет, я напишу примерно так:
int dx = curr_measure_x - prev_measure_x;
coordiate_x += dx;
if (coordiate_x < 0)
    // out of screen


Я не буду разбираться что больше, а что меньше, пусть и все эти значения никогда не могут быть отрицательными по своему физическому смыслу.
Re[10]: Откуда эта лютая любовь к знаковым целым?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 08.05.20 10:22
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>>>для чего, например, argc в main имеет знаковый тип? В каких случаях он может становиться отрицательным?


N>>Это чисто наследие самых ранних реализаций, не захотели менять тип ради мелочи.


ЕМ>Значения времени/даты в tm, значение смещение в va_list (и приведение результата sizeof к int в va_arg) и подобное — тоже "чисто наследие"?


Уже нет, мне кажется. Именно в struct tm можно было бы хранить и без знака, но зачем, если там значения гарантированно меньше соответствующего максимума даже в исходной 16-битке?

Виндовая SYSTEMTIME, для сравнения, имеет полями сплошные WORD. Они исходили из другой логики.
Но, как только начинается вопрос про то, что даты надо вычитать, уже приходится переводить к знаку (об этом тебе уже написали рядом). Ну и зачем эти лишние конверсии?

Для argc я просто не вижу, зачем его можно было бы уводить в минус (особенно с учётом роли argv[0]). Для компонентов даты и времени этот смысл уже есть.
The God is real, unless declared integer.
Re[14]: Откуда эта лютая любовь к знаковым целым?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 08.05.20 10:26
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

N>>Потому что они в голове сперва выполняют проверку на больше/меньше и уже потом из большего вычитают меньшее.

ЕМ>Вас это смущает? Меня — ничуть, коли уж человек от рождения оперирует понятиями "до/после", "выше/ниже" и подобными. А если чей-то возраст вдруг оказался больше возраста любого из его биологических родителей, то это вызывает недоумение даже у дикарей, никогда не слыхавших об отрицательных числах.

Вот из подобной логики математики от Пифагора и аль-Хорезми и вплоть до Кардано вынуждены были расписывать решения уравнений типа x**2+p*x+q=0 на все 4 случая (а для кубического — уже на 8).
А потом пришло следующее поколение с Виетой и упростило весь этот бардакомаразм, введя отрицательные числа.

N>>С отрицательными числами такие проверки часто можно опускать в принципе.

ЕМ>В принципе их опустить нельзя — только применить в другом месте и в другом виде. Ну и я правильно понял, что в своем коде Вы предпочитаете писать "if (a — b < 0)" вместо "if (a < b)"?

Если оно почему-то уже вычислено отдельно — то почему бы и нет? По крайней мере если переполнения при вычитании не происходит, эти сравнения эквивалентны, а если может происходить — то надо включать повышенную осторожность ко всем операциям.
The God is real, unless declared integer.
Re[9]: Откуда эта лютая любовь к знаковым целым?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 08.05.20 10:53
Оценка: 1 (1) +1
Здравствуйте, Mystic Artifact, Вы писали:

MA>>>Любой двоичный тип данных может быть выражен как просто число.

E>>Это не совсем правда, или я не понял о чём ты. Например, не любой указатель в С++ может быть так выражен. Указатель на поле, например, -- это двоичный тип?
MA> Единственная причина, почему указатель не мог быть приравнен к соответствующей размерности числу — это разного рода виды теневой памяти и прочее. Сюда же относится и сегментная память, с которой работают текущие процессоры. Но, она всегда настраивается на "плоский" режим, а C++ не позволяет работать с сегментами. Таким образом это все быстро вырождается в то, что мы имеем 32/64-битные адреса и они де числа.

Что ж вы классику-то не читаете ;(

This machine uses a different numbering scheme for character- and integer-pointers. The same location in memory must be referred to by different addresses depending on the pointer type. A cast between char* and int* actually changes the address inside the pointer.


On this architecture char* or void* are secretly word pointers with an offset stored in the three unused higher-order bits. Thus incrementing char* as an integer value would move to the next word but keep the same offset.


Notable for using a NULL pointer address that is not bitwise zero. In particular it uses segment 07777, offset 0 for the null pointer.


И так далее. Я ещё видел предыдущую версию списка в comp.lang.c FAQ, но сейчас что-то не нашёл, там тоже много странностей.

Нету обязаловки для всех архитектур иметь простые, однородные, сравнимые плоские указатели. Увы. И C не только для x86, мягко говоря.

На самом деле IMHO было бы удобно в каком-то стандартном хедере иметь или не иметь дефайн типа HAVE_FLAT_POINTERS, чтобы знать, где можно применять хаки, а где — нет. Но, как видим, комитеты с этим не согласны.

MA> Я отвечаю по мере. Ну вот ты в теме. Я не отрицаю вообще-то, что, что-то там. Я говорю, что язык не дает. Он дает указатель и все. А из чего он состоит — не дано. Более того, он ссылается всегда сегмент данных. И да. Именно поэтому нельзяпутать из с указателями на функцию, и интерпретировать так же — но готов ли к этому современный код? Нормальный современный код не парится.


Ну учитывая, что 99% "современного кода" это для x86, ARM и немного MIPS — да, не парятся. И даже для ближайших конкурентов типа Power и z/Arch проблем тут нет (если в указатель не включать address space key — тогда вместо 64 бит становится 80, это похоже на сегментацию, но иное — ключ выбирает таблицу для виртуальной памяти).
Только эмбедщики страдают.

MA> Именно. Это и говорит о том, что они не различимы. Разница, в x86 потом происходит только во флагах и их интерпретации. Дело в том, что при 16-битной сетке нет разницы — то ли ты вычьтешь единицу, то ли прибавишь 65535. Мы не говорим о пространственных теориях приводящих к UB. В процессора нет UB, он работает по модулю и отлично и выдает кучу флагов...


И тут вы слегка этак не правы
Прочитайте про различие команд, например, add и addu в MIPS, и вообще про архитектуру в целом.
Флагов там нет, но add, в отличие от addu, вызывает немедленное исключение по обнаружению переполнения.
Следом — про z/Arch, где команда не меняется, но то же самое можно включить битиком в PSW, кому хочется.

Не сильно возражаю по остальному, но не считайте, что весь мир такой плоский

P.S. Кстати, адресацию в x86-64 по FS и GS можно тоже считать отдельным видом адресации. Она используется на практике, например, для thread-local storage. Так что и он не идеально плоский
The God is real, unless declared integer.
Re[6]: Откуда эта лютая любовь к знаковым целым?
От: Patalog Россия  
Дата: 08.05.20 12:38
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

хъ

PD>>>… если в результате арифметики с положительными числами результат оказался отрицательным там, где такого не должно быть,то ошибку надо искать в алгоритме …


P>>ЕМНИП, это UB, нет? Как можно тут рассуждать должно/не должно?


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


ОК, просто мне показалось что тут речь зашла про эффекты signed overflow.

PD>Например, для вычисления ширины из левой границы вычли правую вместо того, чтобы сделать наоборот.


ИМХО, здесь ничем не хуже будут работать беззнаковые, так как получив на выходе "дофига_бодьшое_число" вместо MAX_WIDTH — признак того что что-то пошло не так.
Почетный кавалер ордена Совка.
Re[11]: Откуда эта лютая любовь к знаковым целым?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 08.05.20 12:55
Оценка:
Здравствуйте, netch80, Вы писали:

N>Именно в struct tm можно было бы хранить и без знака, но зачем, если там значения гарантированно меньше соответствующего максимума даже в исходной 16-битке?


Да просто затем, что эти значения по своей сути не имеют знака.

N>Но, как только начинается вопрос про то, что даты надо вычитать, уже приходится переводить к знаку (об этом тебе уже написали рядом). Ну и зачем эти лишние конверсии?


А если даты нужно делить, чтобы, например, вычислить среднее количество дней, которое занимали некие процессы? Давайте уж сразу хранить их в double, сэкономим на конверсиях.
Re[15]: Откуда эта лютая любовь к знаковым целым?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 08.05.20 13:07
Оценка:
Здравствуйте, netch80, Вы писали:

N>Вот из подобной логики математики от Пифагора и аль-Хорезми и вплоть до Кардано вынуждены были расписывать решения уравнений типа x**2+p*x+q=0 на все 4 случая (а для кубического — уже на 8). А потом пришло следующее поколение с Виетой и упростило весь этот бардакомаразм, введя отрицательные числа.


Да что ж это такое-то, а? Вы хоть раз попробуйте понять то, о чем я тут талдычу уже который раз. А талдычу я об исходных данных для вычислений, а не о решениях (результатах). У математиков были все основания обобщать решения, поскольку эти решения, по сути своей, не обязаны быть ни натуральными, ни целыми, ни даже рациональными. А у программистов нет оснований обобщать входные данные, выраженные в натуральных числах, кроме стремления сэкономить на приведениях типов.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.