Чем вы тут занимаетесь или как поделить число на два

Подходили к вам когда-нибудь ваши знакомые или друзья с вопросом: “А чем вы, программисты, вообще занимаетесь, кроме того, что просто тычете по клавишам?”. Наверное, людей и правда интересует, зачем платят деньги за набор (к тому же медленный) текста на клавиатуре, даже если эти люди целый день таскают с собой мобильный телефон1.

Но вопрос есть вопрос. И если попытаться ответить без шутки, что же мы на самом деле делаем (кроме того, что спим и едим). Да, можно попробовать. Ну, думаю, что тем же, чем занимаются и другие инженеры. Пытаемся заставить ресурсы (в нашем случае это вычислительные машины) работать на человека и приносить какую-то пользу (считается ли пользой для человечества перекладывание JSON из одного места в другой?).

Страшилки преобразований. Часть 2

Мне понравилась идея небольших статей, продолжаем. Наверное, лучшее название было бы — страшилки представления, но раз эта вторая часть в серии оставлю прежнее.

// Любой уважающий себя современный микропроцессор:

>>> 0.1 == 0.1
True
>>> 0.1 + 0.1 == 0.2 
True
>>> 0.1 + 0.2 == 0.3
False

// ЧТО?

Как я уже упоминал, программисты боятся арифметики с плавающей точкой. И не зря.

Итак:

package main

//go:noinline
func foo(a, b, c float64) float64 {
	return a*b + c
}

//go:noinline
func bar(a, b, c float64) float64 {
	return barmul(a, b) + c
}

//go:noinline
func barmul(a, b float64) float64 {
	return a * b
}

func main() {
	a := 0.6666666666666
	b := 0.3333333333
	c := 0.2222222

	println(foo(a, b, c) == bar(a, b, c))
}

Предлагаю ответить на вопрос, возможна ли ситуация когда программа распечатает false? Если да, то когда. Предлагаю остановиться тут и подумать.

Страшилки преобразований

Это третья сказка, но вторую никак не допишу. Сегодня без ассемблера. Обещаю.

Надпись на обратной стороне. Осторожно. Неопределённое поведение. При сложении двух знаковых чисел, в случае возникновения переполнения, калькулятор может выдать ошибку или взорваться. ПРОВЕРЯЙТЕ переполнение или ИЗБЕГАЙТЕ складывания чисел.

Если вы программируете на языках C/C++ или варитесь возле этой темы, вам всегда будут попадаться люди, двух типов:

  1. Оставляющие за собой код рождающий неопределённое поведение и отправляющие его на ревью с припиской - да не ссы, я так сто раз делал.
  2. Люди рассказывающие про то, что ваша программа уничтожит весь род человеческий если вы немедленно это не исправите. А лично вы попадёте в ад, где вам вечность будут зачитывать статьи про плюсы PHP.

Что же нам, программистам на Go, когда читаем очередную статью про неопределённое поведение и сопутствующий ей холивар, она вызывает, обычно, ровно такие же эмоции, как и, например, новость про голодающих детей в Уганде1, то есть никакие.

Как же нам хорошо, ведь у нас в языке такого произойти не может.

ИЛИ МОЖЕТ?

А как же строки?

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

Это экспериментальная заметка. Я буду признателен за любой фидбек.

Все правки, очепятки и откровенные ошибки отправляйте на электронный адрес rokkerruslan@protonmail.com, я исправлю это. Также можно внести правки самостоятельно через Pull Request. Буду рад. Стараюсь, как могу, не сильно глубоко уходить в детали и не распыляться по многим темам одновременно, чтобы сохранить некоторую целостность в повествовании и темп рассказа. Сноски содержат более подробное описание блока, его пояснение (или ещё больше запутывают). По ним можно проходить и понять, что имелось в виду в том или ином пункте, если этот пункт в статье показался неочевидным. Также сноски содержат ссылки на дополнительные источники информации1.