Implementation:ClickHouse ClickHouse DecomposedFloat
| Knowledge Sources | |
|---|---|
| Domains | Numeric_Types, Floating_Point |
| Last Updated | 2026-02-08 00:00 GMT |
Overview
A utility for decomposing IEEE-754 floating-point numbers into their constituent parts (sign, exponent, mantissa) and comparing them with integers.
Description
`DecomposedFloat` provides low-level access to the internal representation of floating-point numbers according to the IEEE-754 standard. It extracts the sign bit, exponent, and mantissa from float, double, Float16, and BFloat16 types, and provides methods to:
- Determine if a float represents an integer value
- Compare floats with integers of arbitrary width (including 128 and 256-bit integers)
- Check for special values (NaN, infinity, finite)
- Calculate normalized exponents and signed mantissas
The comparison method implements a total ordering that handles infinities, NaNs, and ensures correct comparison between floating-point and integer types without conversion-induced precision loss.
Usage
Use this implementation when you need to:
- Compare floating-point numbers with large integers without loss of precision
- Determine if a float value is exactly representable as an integer
- Access internal floating-point representation for debugging
- Implement custom floating-point operations or analysis
- Handle edge cases like infinities and NaNs in comparisons
Code Reference
Source Location
- Repository: ClickHouse
- File: base/base/DecomposedFloat.h
- Lines: 1-254
Signature
template <typename T>
struct DecomposedFloat {
using Traits = FloatTraits<T>;
typename Traits::UInt x_uint;
explicit DecomposedFloat(T x);
explicit DecomposedFloat(typename Traits::UInt x);
bool isNegative() const;
int sign() const;
uint16_t exponent() const;
int16_t normalizedExponent() const;
uint64_t mantissa() const;
int64_t mantissaWithSign() const;
bool isIntegerInRepresentableRange() const;
bool isFinite() const;
bool isNaN() const;
template <typename Int> int compare(Int rhs) const;
template <typename Int> bool equals(Int rhs) const;
template <typename Int> bool less(Int rhs) const;
template <typename Int> bool greater(Int rhs) const;
template <typename Int> bool lessOrEquals(Int rhs) const;
template <typename Int> bool greaterOrEquals(Int rhs) const;
};
using DecomposedFloat64 = DecomposedFloat<double>;
using DecomposedFloat32 = DecomposedFloat<float>;
Import
#include <base/DecomposedFloat.h>
I/O Contract
| Input | Type | Description |
|---|---|---|
| x | T (float/double/Float16/BFloat16) | Floating-point value to decompose |
| Output | Type | Description |
|---|---|---|
| sign | int | Sign: -1 (negative), 0 (zero), 1 (positive) |
| exponent | uint16_t | Raw exponent bits |
| mantissa | uint64_t | Raw mantissa bits |
| compare_result | int | -1 (less), 0 (equal), 1 (greater) |
Usage Examples
#include <base/DecomposedFloat.h>
// Decompose a double
DecomposedFloat64 df(3.14159);
int sign = df.sign(); // 1
int16_t exp = df.normalizedExponent(); // 1
uint64_t mantissa = df.mantissa();
bool is_finite = df.isFinite(); // true
// Check if float is exactly an integer
DecomposedFloat64 df2(42.0);
bool is_int = df2.isIntegerInRepresentableRange(); // true
DecomposedFloat64 df3(42.5);
bool is_int2 = df3.isIntegerInRepresentableRange(); // false
// Compare with large integers
DecomposedFloat64 df4(1e18);
Int128 big_int = Int128(1000000000000000000ULL);
int cmp = df4.compare(big_int); // Returns comparison result
// Handle special values
DecomposedFloat64 nan(std::numeric_limits<double>::quiet_NaN());
bool is_nan = nan.isNaN(); // true
bool is_finite_nan = nan.isFinite(); // false
DecomposedFloat64 inf(std::numeric_limits<double>::infinity());
int cmp_inf = inf.compare(1000000); // Returns 1 (inf > any finite)
// Compare floats with 256-bit integers
DecomposedFloat64 df5(1e50);
Int256 huge_int = /* ... */;
bool less = df5.less(huge_int);