Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/7: Рейтинг темы: голосов - 7, средняя оценка - 5.00
1 / 1 / 0
Регистрация: 05.04.2015
Сообщений: 15

Целочисленные литералы и суффиксы, как правильно это функционирует?

02.07.2015, 01:40. Показов 1564. Ответов 7
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем доброго времени суток, снова непонимание, и неудача при поиске ответа, HELP!

Имею следующий пример:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Inches
{
    public static void Main()
    {
        long inches;
        int miles;
 
        miles = 93000000;
 
        Console.WriteLine(miles);
 
        inches = miles * 5280 * 12;
 
        Console.WriteLine("Расстояние составляет "+inches);
    }
    
};
Результат :
93000000
Расстояние составляет -215130112
Для продолжения нажмите любую клавишу . . .


Результат вычислений неправильный, на сколько я понимаю ошибка вызвана тем что значениям 5280 и 12 был автоматически присвоен тип Int. Вывод я такой сделал из этого комментария полученного методом гугль
"Per MSDN "When an integer literal has no suffix, its type is the first of these types in which its value can be represented":
int, uint, long, ulong." - Это верное утверждение? И что в таком случае происходит если я к примеру не буду явно определять тип для литералов с плавающей запятой?

Вот следующий вариант:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Inches
{
    public static void Main()
    {
        long inches;
        int miles;
 
        miles = 93000000;
 
        Console.WriteLine(miles);
 
        inches = miles * 5280 * 12L;
 
        Console.WriteLine("Расстояние составляет "+inches);
    }
    
};
Результат :
93000000
Расстояние составляет -215130112
Для продолжения нажмите любую клавишу . . .


В данном случае ответ тоже не верный, получается у нас что 5280 это int а 12 я определил как long.


Так, продолжаю значит я дальше:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Inches
{
    public static void Main()
    {
        long inches;
        int miles;
 
        miles = 93000000;
 
        Console.WriteLine(miles);
 
        inches = miles * 5280L * 12;
 
        Console.WriteLine("Расстояние составляет "+inches);
    }
    
};
Результат :
93000000
Расстояние составляет 5892480000000
Для продолжения нажмите любую клавишу . . .


Собственно тут ответ верный, причем разница с предыдущем листингом состоит только в том, что я определил уже 5280 как long, а 12 не трогал (на сколько я понял он в данном случае числиться как int).

Ну и в последнем случае, я ставлю суффикс L и около 12 и около 5280, результат получаю верный.

Если утверждение "Per MSDN "When an integer literal has no suffix, its type is the first of these types in which its value can be represented": int, uint, long, ulong." верное, тогда я понимаю природу ошибки, однако я совсем не понимаю как конкретно происходят вычисления и преобразования типов. И как в результате получаются такие значения .

Был бы очень рад если бы кто-то объяснил как точно происходят вычисления в каждом примере и как правильно поступать в таких случаях. Также интересует ситуация с плавающей точкой.

P.S. Либо дайте хотя бы ссылочку где можно порыться. А еще меня интересует почему преобразование начинается с int, а не с byte and sbyte ведь так место вроде же экономиться?
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
02.07.2015, 01:40
Ответы с готовыми решениями:

Можно ли сравнивать строковые литералы? как правильно это сделать?
надо сравнить введенный строковый литерал с одним из доступных. int main() { setlocale(0,""); char const s =15; ...

Целочисленные литералы
Здравствуйте. Читаю книгу и не понятно в одном месте. Написано: целочисленные литералы создают значения типа int. Но можно...

Windows07 не правильно функционирует
открыл программу с помощью MSW07 теперь все открывается с MSW07,помогите ,что делать???

7
 Аватар для diadiavova
7259 / 2606 / 744
Регистрация: 11.04.2015
Сообщений: 4,150
Записей в блоге: 43
02.07.2015, 10:22
Для каждого числового типа определены собственные арифметические операторы. Надеюсь не надо объяснять, что оператор - это просто функция, имеющая инфиксную форму записи. Как любая функция, оператор имеет собственную сигнатуру, то есть в нем определен тип операндов и для числовых типов операторы определены таким образом, что принимают оба операнда одного типа, то есть нет оператора умножения, в котором один операнд был бы инт, а другой лонг. Понимая это обстоятельство, несложно понять как, когда и почему происходит преобразование из инт в лонг. Происходит оно тогда и в тех операторах, когда операторам передаются разнотипные операнды. То есть в тех местах, где тип операндов разный, один из операторов будет преобразован к другому типу.
Теперь рассмотрим ситуации, приведенные в примерах.
int*int*long
Поскольку умножение - левоассоциативный оператор, стало быть вычисление производится слева-направо. То есть сначала выполняется умножение инт-ов, а потом, при выполнении второго оператора уже результат первого вычисления приводится к типу лонг.
int*long*int
Здесь с самого начала операнды разнотипные, поэтому в первом операторе буед выполнено преобразование первого операнда к типу лонг, а во втором - то же самое будет сделано со вторым операндом.
Ошибка же появляется из-за переполнения значения инт. То есть если бы результат первого умножения не превышал максимального значения типа инт, то ошибки бы вообще не было.
2
1 / 1 / 0
Регистрация: 05.04.2015
Сообщений: 15
02.07.2015, 18:33  [ТС]
diadiavova, Спасибо, в принципе понятно. Вот только хотел уточнить.
Получается что первым делом обращаем внимание на приоритет оператора и/или на скобки (если они есть в выражении), таким образом получаем последовательность действий. Исходя из этой последовательности можем выяснить типы данных участвующих в операции (int*long, int*int). Ключевой момент, если я правильно понял, заключается в 2 особенностях:

1. Последовательность операторов.
2. Если возникают операции с разными типами данных, получается что результат приводиться к типу, который имеет больший размер. (int*long*int).
(int*long > результат в long), (long(он же результат предыдущей операции)*int > результат в long).
Поправьте пожалуйста, если что не так понял.
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
02.07.2015, 18:58
Лучший ответ Сообщение было отмечено ArtemHelloWorld как решение

Решение

Цитата Сообщение от ArtemHelloWorld Посмотреть сообщение
Если возникают операции с разными типами данных, получается что результат приводиться к типу, который имеет больший размер.
Не совсем.
Как сказал выше товарищ diadiavova, операторы — это не более чем функции, со своими параметрами и возвращаемыми значениями.
В шарпе по умолчанию имеется четыре оператора умножения над целочисленными типами:
C#
1
2
3
4
int operator *(int x, int y);
uint operator *(uint x, uint y);
long operator *(long x, long y);
ulong operator *(ulong x, ulong y);
Или, если угодно, так:
C#
1
2
3
4
int Multiply(int x, int y);
uint Multiply(uint x, uint y);
long Multiply(long x, long y);
ulong Multiply(ulong x, ulong y);
Переписываем ваш первый пример:
C#
1
inches = Multiply(Multiply(miles, 5280), 12);
Дальше вступает в дело резолюция перегрузок.
Для того, чтобы определить тип первого параметра внешнего вызова Multiply, надо определить перегрузку внутреннего вызова.
miles — int, 5280 — int, лучший подходящий метод — вот этот:
C#
1
int Multiply(int x, int y);
Возвращает он int, значит тип первого параметра — инт.
12 — тоже инт, значит перегрузка внешнего вызова больше всего подходит такая же:
C#
1
int Multiply(int x, int y);
Результат, как видно, int. Результат высчитывается и значение присваивается переменной inches, попутно конвертиремое в ее тип long.

Второй пример:
C#
1
inches = Multiply(Multiply(miles, 5280), 12L);
Тот же самый процесс: miles — int, 5280 — int, выбирается первая перегрузка, которая возвращает тип int.
Дальше определяется перегрузка внешнего метода: результат внутреннего Multiply — int, 12L — long.
Первая перегрузка не подходит, т.к. второй параметр типа long неявно не конвертируется в int.
Вторая перегрузка не подходит, т.к. ни первый, ни второй параметры не конвертируются неявно в uint.
Третья перегрузка подходит, т.к. первый параметр int конвертируется в long, а второй параметр — уже long.
Четвертая перегрузка не подходит, т.к. ни один из параметров не конвертируется неявно в ulong.

Из списка выше получается только одна подходящая перегрузка — это третья:
C#
1
long Multiply(long x, long y);
Результат первого умножения конвертируется в long и передается в метод вместе с аргументом 12L, метод возвращает long, который и присваивается переменной inches.

Третий пример:
C#
1
inches = Multiply(Multiply(miles, 5280L), 12);
Опять двадцать пять: сначала определяется тип первого аргумента, для чего нужно определить подходящую перегрузку внутреннего вызова. Аргументы: miles — int, 5280L — long.
Как и в предыдущем примере, выбор падает на третью перегрузку, т.к. к ней подходят оба аргумента:
C#
1
long Multiply(long x, long y);
Метод возвращает long, значит тип первого параметра внешнего вызова — long.
Дальше делается то же самое для внешнего вызова:
Результат внутреннего вызова — long, второй аргумент 12 — int.
Опять перегрузка выпадает на третью, она выполняется, возвращаемое значение типа long присваивается переменной inches.
3
 Аватар для diadiavova
7259 / 2606 / 744
Регистрация: 11.04.2015
Сообщений: 4,150
Записей в блоге: 43
02.07.2015, 19:46
Цитата Сообщение от ArtemHelloWorld Посмотреть сообщение
Получается что первым делом обращаем внимание на приоритет оператора и/или на скобки (если они есть в выражении)
В данном случае на ассоциативность. Одним словом: всегда надо понимать последовательность выполнения действий. А еще лучше - писать так, чтобы она была очевидной и легко читалась.
Цитата Сообщение от ArtemHelloWorld Посмотреть сообщение
к типу, который имеет больший размер.
Тут не только в размере дело, просто бывают сужающие преобразования, а бывают расширяющие. Сужающее преобразование потенциально может привести к потере данных, поэтому предпочтение отдается преобразованиям расширяющим. В принципе kolorotur все очень подробно расписал, что происходит в данном случае, так что, кроме этих небольших пояснений добавить особо нечего.
1
1 / 1 / 0
Регистрация: 05.04.2015
Сообщений: 15
02.07.2015, 19:58  [ТС]
kolorotur, diadiavova, Спасибо, теперь все(!) понятно стало.
0
0 / 0 / 0
Регистрация: 20.05.2016
Сообщений: 3
22.05.2016, 20:14
Я решил проблему вот так, возможно более простым является просто помнить, что в правой части хотя бы 1 литерал должен быть такого же типа, как и единственный в левой. Верно ли это?
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
using System;
class Inches
{
    public static void Main()
    {
        ulong inches;
        int miles;
 
        miles = 93000000;
 
        Console.WriteLine(miles);
 
        inches = (ulong)miles * 5280 * 12;
 
        Console.WriteLine("Расстояние составляет " + inches);
    }
 
};
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
22.05.2016, 21:49
Цитата Сообщение от Дамир_84 Посмотреть сообщение
в правой части хотя бы 1 литерал должен быть такого же типа, как и единственный в левой. Верно ли это?
Не обязательно.
Например:
C#
1
byte x = 124 + 3;
Справа оба литерала — инты, а результат — байт.

C#
1
uint x = -20 + 40;
Справа оба литерала — инты, а результат — беззнаковый инт.

C#
1
2
3
byte a = 12;
byte b = 20;
byte c = a + b;
А вот это уже работать не будет, хотя обе переменные — byte, но результат будет int.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
22.05.2016, 21:49
Помогаю со студенческими работами здесь

Как это реализовать? И как это правильно называется?
Всем привет. Хочу достигнуть такого эффекта как на этом сайте http://www.kocha.com.au/ Суть эффекта в том, что мы переходим по страницы...

Как посмотреть суффиксы CSS-классов модулей в шаблоне?
Скажите пожалуйста, как посмотреть суффиксы CSS-классов модулей в шаблоне? В демо-шаблона они не представлены или я их не вижу!? Возможно...

Как это правильно называется?
Добрый день, как это правильно называется (хочу почитать про это поподробнее в интернете, но не могу ввиду не знания названия). В...

Как это правильно называется
ИмяИнтерфейса название= new КлассКоторыйРеализует(); Это ведь полиформизм в каком то роде? По сути ведь мы создаем объект класса...

Как это правильно реализовать
Осуществить циклический сдвиг элементов квадратной матрицы размером М х N вправо на k элементов таким образом: элементы первой строки...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему
Новые блоги и статьи
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка библиотек: SDL3, Box2D, FreeType, SDL3_ttf, SDL3_mixer и SDL3_image из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual Studio. . . .
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru