Десятичная запятая
Затронули тут в одном из айтишных чатов тему десятичной запятой — я считаю, что в русском тексте должна использоваться десятичная запятая, хотя и понимаю, что программистам привычнее точка, так как во всех языках программирования используется именно она.
На этом месте я вдруг задумался — видел ли я хоть раз язык, где используется десятичная запятая?
Так и не вспомнил, зато на память пришёл забавный баг, который был когда-то в четвёртом ПХП: если установить русскую локаль, появлялась возможность складывать числа в строках, используя десятичную запятую:
<?php
var_dump('0,4' + '0,7');
setlocale(LC_ALL, 'ru_RU.koi8r');
var_dump('0,4' + '0,7');
Как можно убедиться онлайн, результат будет следующим:
int(0)
float(1,1)
Работает в версиях 4.0—4.2, в 4.3 уже не повторяется. Я не помню каким образом на него наткнулся, но чувство недоумения от этого эффекта до сих пор живо в моей памяти.
В 2000-х годах в суперкомпьютерном центра МГУ эксплуатировался NUMA сервер от IBM. Сейчас не могу вспомнить, какой именно модели, поскольку в последний раз получал к нему доступ десять лет назад в 2013 году. На сервере использовался родной компилятор от IBM и этот компилятор имел замечательную ошибку. При установленной русской локали ru_RU он не мог распарсить вещественные числа в программах, поскольку считал, что разделителем десятичных знаков должна быть запятая. Ради интереса, я поменял все десятичные точки на запятые, но это не помогло: в зависимости от контекста, эти запятые интерпретировались либо как разделители параметров функции, либо как оператор «запятая», что, в общем-то, было вполне ожидаемо.
Когда моя коллега впервые наткнулась на эту ошибку у меня ушло минут 40 для того, чтобы осознать, что дело не в кодировке и не в невидимых символах в окрестности точек, а именно в локали.
Ещё недавно наткнулся на то, что при установленной русской локали вывод вещественных чисел в C++ двумя разными способами дает разные результаты.
float f=3.14;
// Укажем, что мы хотим форматировать числа, даты, валюты и пр.
// по правилам русского языка
setlocale(LC_ALL, «Russian»);
// libc по умолчанию использует пользовательские настройки
printf(«%f\n», f); // 3,14
// Стандартные потоки по умолчанию используют локаль POSIX
std::cout << f << std::endl; // 3.14
// Для вывода по национальным правилам надо проделать не совсем очевидные вещи
// Создание копии пользовательской локали
std::locale loc(«„);
std::cout << „Locale name = “ << loc.name() << std::endl; //Russian
// Установка формата вывода в соответствии с указанной локалью
std::cout.imbue(loc);
// Вот теперь можно выводить числа в национальном формате
std::cout << f << std::endl; // 3,14
Ага, спасибо! Я сейчас смутно вспоминаю, что в ПХП 4 с той же проблемой столкнулся — при выставлении локали он переставал воспринимать числа с десятичной точкой.