Еще более простая модификация подхода, обсуждаемого в комментариях:
Умножьте на 1000 и преобразуйте в целое число с fistp
(с округлением по умолчанию до ближайшего) вместо просто округление до целочисленного значения long double
с использованием frndint
.
Младшие 3 десятичные цифры этого целого числа являются дробной частью вашего числа. т.е. у вас теперь есть десятичная дробь точка. div
на 1000 дает вам частное (целая часть) и остаток (дробная часть). Печать обеих частей с .
между ними.
Вы захотите выполнить ручное преобразование int-> string ( Как напечатать целое число в программировании на уровне сборки без printf из библиотеки c? ) или иначе печатать начальные нули в дробной части. (Таким образом, 2.062
не превращается в 2.62
)
Это проще, чем разделение на целые и дробные части в FP, что потребует округления с усечением до нуля, чтобы убедиться, что вы получили неотрицательная дробная часть. Целочисленное деление естественным образом усекается до нуля, но унаследованное преобразование x87 FP-> int может использовать только режим округления по умолчанию. (За исключением SSE3 fisttp
.) SSE1 / 2 имел XMM FP-> int преобразования с усечением или текущим режимом округления, так как они были введены, как cvttsd2si
против cvtsd2si
Недостаток: переполняет 32-разрядное целое число для меньших чисел с плавающей запятой , поскольку одно 32-разрядное целое число должно содержать x * 1000
.
Другой способ - использовать x - (int)x
для получения дробной части и только умножение на дробной части на 1000.0
. Это приводит к (int)x
в отдельном целом числе от дробной части, с x*1000
, существующим только с плавающей запятой, а не int32_t
.
Интересный факт:
AVX512DQ есть инструкция для получения дробной части напрямую: VREDUCESD xmm1, xmm2, xmm3 / m64, imm8 (и версии ss / ps / pd). Это часть, которую SSE4 roundsd / vrndscalesd будет отбрасывать при сохранении целочисленной части. Еще интереснее: можно хранить указанное количество битов дроби. Но, конечно, это биты двоичной дроби, а не десятичные разряды.
В наши дни большинство процессоров x86 имеют SSE4.1, но AVX512DQ только у настольных компьютеров высшего класса Skylake-X и современных Xeon. : / И Ледяное озеро Ноутбуки.