Это сайт — моя персональная записная книжка. Интересна мне, по большей части, история, своя жизнь и немного программирование.

Десятичная запятая

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

На этом месте я вдруг задумался — видел ли я хоть раз язык, где используется десятичная запятая?

Так и не вспомнил, зато на память пришёл забавный баг, который был когда-то в четвёртом ПХП: если установить русскую локаль, появлялась возможность складывать числа в строках, используя десятичную запятую:

<?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 уже не повторяется. Я не помню каким образом на него наткнулся, но чувство недоумения от этого эффекта до сих пор живо в моей памяти.

1 комментарий
Александр Игумнов 2023

В 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

Евгений Степанищев 2023

Ага, спасибо! Я сейчас смутно вспоминаю, что в ПХП 4 с той же проблемой столкнулся — при выставлении локали он переставал воспринимать числа с десятичной точкой.