Kujivunia

Пользователь

Регистрация: 10.01.2015

Сообщения: 5545

Рейтинг: 958

Нарушения: 10

Kujivunia

Регистрация: 10.01.2015

Сообщения: 5545

Рейтинг: 958

Нарушения: 10

Знаете, в чём разница этих двух картинок? 

 

image.pngimage.png

 

В строчке feelsrageman.png?1592047238

dist = height / (plank * 2.0 - height) / Math.Cos(cam.fov * 0.5 - (bar * cam.fov /width));

dist = height / (plank * 2 - height) / Math.Cos(cam.fov / 2 - (bar * cam.fov / width));

 

Ну смотрите. Я большую часть времени программировал на Паскале. 

Если пишу на Паскале 

a/b, то получаю нормальное деление. ВСЕГДА. 

a div b, то получаю целочисленное деление. ВСЕГДА. 

 

Но если я пишу на C#, то он внезапно начинает играть в Вангу и решать за меня, чё я там такое хотел. pepejeez.png?1592046683

a/b он тебе преобразует и в целочисленное деление, и в нормальное, причём ЧСХ вообще без предупреждения, ни тебе ошибки, ни тебе warning. feelsrageman.png?1592047238feelsrageman.png?1592047238feelsrageman.png?1592047238

Это напоминает мне офигенный опыт из Жаваскрипта, когда она выдавала бредовые результаты в одной из функций, потому что в каком-то параметре у меня была функция трёх переменных, в которую я забыл передать эту третью переменную. И Джаваскрипт усердно чёто-там наприводил и выплюнул, не дав мне ни ошибки, не предупреждения, нифига. weSmart.png?1616514285

 

Я потратил три с половиной часа чтобы этот баг найти. Что там, что тут. Я умудрился найти математическое и тригонометрическое описание своей задачи и даже начал писать и выводить все формулы заново. 200iq.gif?1621125445Хотя знал, что в коде они у меня правильные, потому что я этот код построчно перенёс, собственно, с Паскаля. Где всё клёво работало. 

 

Спасибо большое Мелкомягкие за то, что в нормальном языке сделали шизоидный плавающий тип вычислений базового оператора bc7d536709b2c67176076ee260da9245.gif

 

П.С. Ну я затестил полы тут. Буду щас тестить оптимизации всякие. Потому что фэпэс падает с 200 до 15. Потом добавлю существ с анимациями. Ну и в принципе готово. 

KastomKnuckles

Пользователь

Регистрация: 05.07.2014

Сообщения: 10784

Рейтинг: 3959

KastomKnuckles

Регистрация: 05.07.2014

Сообщения: 10784

Рейтинг: 3959

Учи ассемблер

Удалено 624055

Пользователь

Регистрация: 24.03.2016

Сообщения: 41

Рейтинг: 19

Удалено 624055

Регистрация: 24.03.2016

Сообщения: 41

Рейтинг: 19

img
Kujivunia сказал(а):

Но если я пишу на C#, то он внезапно начинает играть в Вангу и решать за меня, чё я там такое хотел

Нажмите, чтобы раскрыть...

жаль что на любом сайте по Си Шарпу ясно написано, что если a,b целые (int) то результат будет целым (int) а если a или b float то ответ float

Kujivunia

Пользователь

Регистрация: 10.01.2015

Сообщения: 5545

Рейтинг: 958

Нарушения: 10

Kujivunia

Регистрация: 10.01.2015

Сообщения: 5545

Рейтинг: 958

Нарушения: 10

VovkaKalibrovka сказал(а):

жаль что на любом сайте по Си Шарпу ясно написано, что если a,b целые (int) то результат будет целым (int) а если a или b float то ответ float

Нажмите, чтобы раскрыть...

Вот щас бы перед использованием весьма определённого и простейшего оператора деления искать чё он там делает. 

 

А давайте мы для каждого токена будем так делать? 

Вдруг если перед { написать 2 пробела, то она скипается каждый чётный цикл, а если 3 пробела, то каждый нечётный цикл, а если 1 пробел, то цикл просто не выполняется? 

А вдруг если мы складываем дабл с интом, то получаем в ответе округлённый вверх результат деления инта на дабл? А вдруг если мы пишем 

int d; это значит, что мы сделали класс cPowCannon с полем double p = 8; и методом public static int qwe(Point d) => 5846; 

strogan

Пользователь

Регистрация: 03.01.2013

Сообщения: 1075

Рейтинг: 377

strogan

Регистрация: 03.01.2013

Сообщения: 1075

Рейтинг: 377

ну да, создатель C# еще тайпскрипт сделал

kremennik

Куратор других игр и разного

Регистрация: 10.11.2011

Сообщения: 45467

Рейтинг: 27595

kremennik

Регистрация: 10.11.2011

Сообщения: 45467

Рейтинг: 27595

img
Kujivunia сказал(а):

Вот щас бы перед использованием весьма определённого и простейшего оператора деления искать чё он там делает. 

Нажмите, чтобы раскрыть...

 

Ну C# строго типизирован, в принципе логично что он не выплевывает float из операции над int

И да, в JS как раз бы не было такой проблемы, там бы все норм поделилось

Удалено 624055

Пользователь

Регистрация: 24.03.2016

Сообщения: 41

Рейтинг: 19

Удалено 624055

Регистрация: 24.03.2016

Сообщения: 41

Рейтинг: 19

img
Kujivunia сказал(а):

Вот щас бы перед использованием весьма определённого и простейшего оператора деления искать чё он там делает. 

 

А давайте мы для каждого токена будем так делать? 

Вдруг если перед { написать 2 пробела, то она скипается каждый чётный цикл, а если 3 пробела, то каждый нечётный цикл, а если 1 пробел, то цикл просто не выполняется? 

А вдруг если мы складываем дабл с интом, то получаем в ответе округлённый вверх результат деления инта на дабл? А вдруг если мы пишем 

int d; это значит, что мы сделали класс cPowCannon с полем double p = 8; и методом public static int qwe(Point d) => 5846; 

Нажмите, чтобы раскрыть...

если б ты по языкам не прыгал а учил один то знал бы особенности своего языка

Spookyfish

Пользователь

Регистрация: 03.04.2022

Сообщения: 1852

Рейтинг: 451

Нарушения: 104

Spookyfish

Регистрация: 03.04.2022

Сообщения: 1852

Рейтинг: 451

Нарушения: 104

на сколько я помню результат зависит от того, как ты эту переменную объявил. это начало любого учебника по яп.

Kujivunia

Пользователь

Регистрация: 10.01.2015

Сообщения: 5545

Рейтинг: 958

Нарушения: 10

Kujivunia

Регистрация: 10.01.2015

Сообщения: 5545

Рейтинг: 958

Нарушения: 10

kremennik сказал(а):

 

Ну C# строго типизирован, в принципе логично что он не выплевывает float из операции над int

И да, в JS как раз бы не было такой проблемы, там бы все норм поделилось

Нажмите, чтобы раскрыть...

Строго типизирован - это когда функция с типом возвращаемого значения double будет возвращать чистый double, а не делать 

 

(double)((int)result)

kremennik

Куратор других игр и разного

Регистрация: 10.11.2011

Сообщения: 45467

Рейтинг: 27595

kremennik

Регистрация: 10.11.2011

Сообщения: 45467

Рейтинг: 27595

img
Kujivunia сказал(а):

Строго типизирован - это когда функция с типом возвращаемого значения double будет возвращать чистый double, а не делать 

 

(double)((int)result)

Нажмите, чтобы раскрыть...

 

Сложно

Kujivunia

Пользователь

Регистрация: 10.01.2015

Сообщения: 5545

Рейтинг: 958

Нарушения: 10

Kujivunia

Регистрация: 10.01.2015

Сообщения: 5545

Рейтинг: 958

Нарушения: 10

kremennik сказал(а):

 

Сложно

Нажмите, чтобы раскрыть...

Ну так в этом и претензия, какой шизоид вообще решил, что офигенной идеей будет сделать перегруженный оператор, который в половине случаев выплёвывает result, а в другой половине приведёт его к инту, а потом это приведение приведёт обратно в дабл (double)((int)result)

Mirajana

Пользователь

Регистрация: 02.07.2012

Сообщения: 10572

Рейтинг: 6634

Mirajana

Регистрация: 02.07.2012

Сообщения: 10572

Рейтинг: 6634

img

'2'+ 2 = 22 спасибо 

Zacateca

Пользователь

Регистрация: 22.12.2017

Сообщения: 34330

Рейтинг: 13380

Нарушения: 25

Zacateca

Регистрация: 22.12.2017

Сообщения: 34330

Рейтинг: 13380

Нарушения: 25

1)Ты сам явно не определил тип константы/переменой

Поэтому стоит почитать как ЯП поступает в этих случаях и что возвращает при простых мат операциях (неявное приведение типа).

https://learn.microsoft.com/ru-ru/dotnet/csharp/language-reference/builtin-types/numeric-conversions#implicit-numeric-conversions

2) А разве JS должен проверять что ты там забыл передать в функцию?

Lambda-chan

Пользователь

Регистрация: 26.07.2012

Сообщения: 4615

Рейтинг: 8637

Lambda-chan

Регистрация: 26.07.2012

Сообщения: 4615

Рейтинг: 8637

Ну это так почти во всех языках работает, причем в независимости от типизации. Кроме хаскелля и паскаля, не вспомню примеров, где бы это работало по-другому.

xdy

Пользователь

Регистрация: 05.08.2022

Сообщения: 426

Рейтинг: 90

xdy

Регистрация: 05.08.2022

Сообщения: 426

Рейтинг: 90

Lambda-chan сказал(а):

Ну это так почти во всех языках работает, причем в независимости от типизации. Кроме хаскелля и паскаля, не вспомню примеров, где бы это работало по-другому.

Нажмите, чтобы раскрыть...

Фу первый раз модера анимешника увидел 

YoshkinKot

ъ

Регистрация: 20.06.2016

Сообщения: 14479

Рейтинг: 5669

YoshkinKot

Регистрация: 20.06.2016

Сообщения: 14479

Рейтинг: 5669

kremennik сказал(а):

Ну C# строго типизирован, в принципе логично что он не выплевывает float из операции над int

И да, в JS как раз бы не было такой проблемы, там бы все норм поделилось

Нажмите, чтобы раскрыть...

Не, сильная типизация это точно не про то, что A, A -> A. Это называется бинарная операция с внутренним законом композиции.

 

Вообще лучше не использовать выражения: "слабо типизированный язык", "сильно типизированный язык". Потому что консенсуса, нормального определения что это такое вообще, ты не особо найдёшь.

 

Lambda-chan сказал(а):

Ну это так почти во всех языках работает, причем в независимости от типизации. Кроме хаскелля и паскаля, не вспомню примеров, где бы это работало по-другому.

Нажмите, чтобы раскрыть...

Ну python, clojure (многие другие лиспы тоже), прологи. Где всякие // и quot для целочисленного подележа.

E1ektr0

Пользователь

Регистрация: 02.09.2013

Сообщения: 617

Рейтинг: 252

E1ektr0

Регистрация: 02.09.2013

Сообщения: 617

Рейтинг: 252

img
Kujivunia сказал(а):

 

dist = height / (plank * 2.0 - height) / Math.Cos(cam.fov * 0.5 - (bar * cam.fov /width));

dist = height / (plank * 2 - height) / Math.Cos(cam.fov / 2 - (bar * cam.fov / width));

 

Нажмите, чтобы раскрыть...

Да напиши dist = height / (plank * 2d - height) / Math.Cos(cam.fov / 2d - (bar * cam.fov / width));

а cam.fov почему int? plank почему int? какой в этом смысл?

Да и как сказали выше, в c# всё чётко, есть явное и не явное привидение. Либо корректно объявляешь типы, либо полагаешься на своё знание неявного привидение. Как ты понимаешь, название не просто так.

Kujivunia

Пользователь

Регистрация: 10.01.2015

Сообщения: 5545

Рейтинг: 958

Нарушения: 10

Kujivunia

Регистрация: 10.01.2015

Сообщения: 5545

Рейтинг: 958

Нарушения: 10

E1ektr0 сказал(а):

Да напиши dist = height / (plank * 2d - height) / Math.Cos(cam.fov / 2d - (bar * cam.fov / width));

а cam.fov почему int? plank почему int? какой в этом смысл?

Да и как сказали выше, в c# всё чётко, есть явное и не явное привидение. Либо корректно объявляешь типы, либо полагаешься на своё знание неявного привидение. Как ты понимаешь, название не просто так.

Нажмите, чтобы раскрыть...

Ничё не чётко, у него динамическая нестрогая типизация говна. В паскале всё чётко. В ассемблере всё чётко. А тут нет. 

 

Насчёт типов. 

dist - double

height - int

plank - int

2 - int (должен быть) 

cam.fov - double (почему ты подумал что инт?)

bar - int

width - int

Ну, Math.Cos очевидно double возвращает ещё. 

 

Ну т.е. моя логика: 

double = height/(int) / double

double = int / int / double

Ну тут уже по левой части выражения, что не нужно ничего к инту приводить, я же в дабл считаю. Но нет, он решает привести. Понятия не имею в каком порядке он считает, у него слева дабл, справа дабл, а ответ он приводит к инту а потом обратно к даблу KEKW.png?1616515034

 

image.png

qt_

Пользователь

Регистрация: 14.09.2020

Сообщения: 8674

Рейтинг: 11988

qt_

Регистрация: 14.09.2020

Сообщения: 8674

Рейтинг: 11988

img

Ну Паскаль это вообще рофл. Ты реально на нём что-то писал, или просто только учился прогать?

 

Бтв че это за проект? Я тоже в какой-то момент пытался сделать псевдо 3д игрушку, но забил быстро

Mask of Sadness

Пользователь

Регистрация: 12.06.2020

Сообщения: 2559

Рейтинг: 1450

Нарушения: 10

Mask of Sadness

Регистрация: 12.06.2020

Сообщения: 2559

Рейтинг: 1450

Нарушения: 10

Учи язык. Ради интереса открыл метанит, арифметические операторы и там про это написано. Хотя логика неочевидная, да

В Dart гораздо удобнее реализовано, есть оператор / который возвращает double и ~/ возвращает int.

Kujivunia

Пользователь

Регистрация: 10.01.2015

Сообщения: 5545

Рейтинг: 958

Нарушения: 10

Kujivunia

Регистрация: 10.01.2015

Сообщения: 5545

Рейтинг: 958

Нарушения: 10

Mask of Sadness сказал(а):

Учи язык. Ради интереса открыл метанит, арифметические операторы и там про это написано. Хотя логика неочевидная, да

В Dart гораздо удобнее реализовано, есть оператор / который возвращает double и ~/ возвращает int.

Нажмите, чтобы раскрыть...
Kujivunia сказал(а):

Вот щас бы перед использованием весьма определённого и простейшего оператора деления искать чё он там делает. 

 

А давайте мы для каждого токена будем так делать? 

Вдруг если перед { написать 2 пробела, то она скипается каждый чётный цикл, а если 3 пробела, то каждый нечётный цикл, а если 1 пробел, то цикл просто не выполняется? 

А вдруг если мы складываем дабл с интом, то получаем в ответе округлённый вверх результат деления инта на дабл? А вдруг если мы пишем 

int d; это значит, что мы сделали класс cPowCannon с полем double p = 8; и методом public static int qwe(Point d) => 5846; 

Нажмите, чтобы раскрыть...

 

morecore

Пользователь

Регистрация: 19.07.2013

Сообщения: 1132

Рейтинг: 322

morecore

Регистрация: 19.07.2013

Сообщения: 1132

Рейтинг: 322

просто есть такая тема как матчасть, сужение типов, динамик каст и т.д.

не зная базу че то делать тот еще прикол

Mask of Sadness

Пользователь

Регистрация: 12.06.2020

Сообщения: 2559

Рейтинг: 1450

Нарушения: 10

Mask of Sadness

Регистрация: 12.06.2020

Сообщения: 2559

Рейтинг: 1450

Нарушения: 10

Kujivunia сказал(а):

 

Нажмите, чтобы раскрыть...

ну пойди против ветра поссы

"Вот щас бы перед использованием весьма определённого и простейшего действия, как поссать, чекать какой-то там ветер"

Valkyria

Пользователь

Регистрация: 15.06.2014

Сообщения: 524

Рейтинг: 209

Valkyria

Регистрация: 15.06.2014

Сообщения: 524

Рейтинг: 209

Ну, вроде, уже все сказали, что это норма для некоторых языков

int number = 5;

float floatNumber = number / 2; //ответ: 2 т.к. int / int

Если ты делаешь такие операции, то надо ставить литералы(ещё называют суффиксами)

int number = 5;

float floatNumber = number / 2f; //ответ: 2.5

F / f - float

M / m - decimal

D / d - double

L / l - long

 

 

Kujivunia сказал(а):

 

a/b он тебе преобразует и в целочисленное деление, и в нормальное, причём ЧСХ вообще без предупреждения, ни тебе ошибки, ни тебе warning. 

Нажмите, чтобы раскрыть...

Купи себе Resharper(R#) для студии. Там есть проверка на "PossibleLossOfFraction" и тебе подсветит, где ты должен посмотреть.

С точки зрения спецификации C# и компилятора, эта валидная запись и все твои хотелки про предупреждения, то это надо обращаться ко всяким Roslyn анализаторам, PVS-studio, Resharper и так далее. 

 

Kujivunia сказал(а):

 

Я потратил три с половиной часа чтобы этот баг найти.

Нажмите, чтобы раскрыть...

Как-то долго, такое обычным дебаггингом должно находиться быстро.

 

Когда делаешь такие вещи, лучше свою платформу изучить. Есть ещё такая штука как Floating Point Arithmetic и у .NET тоже будут свои заморочки

float x = 5.05f;

float y = 0.95f;

Console.WriteLine((x + y) == 6.0f); //Resharper тоже тебя предупредит

Ответ true или false будет зависить от рантайма, от битности программы и от железа.

 

В .NET 5, оба x86 и x64 дают true.

В .NET 4.7, x86 дает false, но на x64 будет true.

И т.д.

 

Kemoin

Пользователь

Регистрация: 14.11.2019

Сообщения: 13206

Рейтинг: 8321

Kemoin

Регистрация: 14.11.2019

Сообщения: 13206

Рейтинг: 8321

VovkaKalibrovka сказал(а):

жаль что на любом сайте по Си Шарпу ясно написано, что если a,b целые (int) то результат будет целым (int) а если a или b float то ответ float

Нажмите, чтобы раскрыть...

не проще все на флоатах делать, дабы не было косяка в любом случае? 

я так на питоне делаю и не парюсь Okayg.png?1639663029