2023-07-24 17:36:49 +02:00
|
|
|
|
# Text Output
|
|
|
|
|
|
2024-02-27 13:58:06 +01:00
|
|
|
|
Besides providing dimensional analysis and unit conversions, the library also tries hard to print
|
|
|
|
|
any quantity in the most user-friendly way. We can print the entire quantity or its
|
|
|
|
|
selected parts (numerical value, unit, or dimension).
|
2023-07-24 17:36:49 +02:00
|
|
|
|
|
|
|
|
|
!!! note
|
|
|
|
|
|
2024-02-27 13:58:06 +01:00
|
|
|
|
The library does not provide a text output for quantity points. The quantity stored inside
|
|
|
|
|
is just an implementation detail of this type. It is a vector from a specific origin.
|
|
|
|
|
Without the knowledge of the origin, the vector by itself is useless as we can't determine
|
|
|
|
|
which point it describes.
|
2023-08-04 14:35:20 +02:00
|
|
|
|
|
2024-02-27 13:58:06 +01:00
|
|
|
|
In the current library design, point origin does not provide any text in its definition.
|
|
|
|
|
Even if we could add such information to the point's definition, we would not
|
|
|
|
|
know how to output it in the text. There may be many ways to do it. For example, should we
|
|
|
|
|
prepend or append the origin part to the quantity text?
|
2023-07-24 17:36:49 +02:00
|
|
|
|
|
2024-02-27 13:58:06 +01:00
|
|
|
|
For example, the text output of `42 m` for a quantity point may mean many things. It may be
|
|
|
|
|
an offset from the mountain top, sea level, or maybe the center of Mars.
|
|
|
|
|
Printing `42 m AMSL` for altitudes above mean sea level is a much better solution, but the
|
|
|
|
|
library does not have enough information to print it that way by itself.
|
2023-07-24 17:36:49 +02:00
|
|
|
|
|
2024-02-27 13:58:06 +01:00
|
|
|
|
Please let us know if you have a good idea of how to solve this issue.
|
2023-11-30 10:53:29 +01:00
|
|
|
|
|
|
|
|
|
|
2024-02-27 13:58:06 +01:00
|
|
|
|
## Predefined symbols
|
2023-11-30 10:53:29 +01:00
|
|
|
|
|
2024-02-27 13:58:06 +01:00
|
|
|
|
The definitions of dimensions, units, prefixes, and constants require assigning text symbols
|
|
|
|
|
for each entity. Those symbols will be composed by the library's framework to express dimensions
|
|
|
|
|
and units of derived quantities.
|
|
|
|
|
|
|
|
|
|
=== "Dimensions"
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
inline constexpr struct dim_length : base_dimension<"L"> {} dim_length;
|
|
|
|
|
inline constexpr struct dim_mass : base_dimension<"M"> {} dim_mass;
|
|
|
|
|
inline constexpr struct dim_time : base_dimension<"T"> {} dim_time;
|
|
|
|
|
inline constexpr struct dim_electric_current : base_dimension<"I"> {} dim_electric_current;
|
|
|
|
|
inline constexpr struct dim_thermodynamic_temperature : base_dimension<{u8"Θ", "O"}> {} dim_thermodynamic_temperature;
|
|
|
|
|
inline constexpr struct dim_amount_of_substance : base_dimension<"N"> {} dim_amount_of_substance;
|
|
|
|
|
inline constexpr struct dim_luminous_intensity : base_dimension<"J"> {} dim_luminous_intensity;
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
=== "Units"
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
inline constexpr struct second : named_unit<"s", kind_of<isq::time>> {} second;
|
|
|
|
|
inline constexpr struct metre : named_unit<"m", kind_of<isq::length>> {} metre;
|
|
|
|
|
inline constexpr struct gram : named_unit<"g", kind_of<isq::mass>> {} gram;
|
|
|
|
|
inline constexpr struct kilogram : decltype(kilo<gram>) {} kilogram;
|
|
|
|
|
|
|
|
|
|
inline constexpr struct newton : named_unit<"N", kilogram * metre / square(second)> {} newton;
|
|
|
|
|
inline constexpr struct joule : named_unit<"J", newton * metre> {} joule;
|
|
|
|
|
inline constexpr struct watt : named_unit<"W", joule / second> {} watt;
|
|
|
|
|
inline constexpr struct coulomb : named_unit<"C", ampere * second> {} coulomb;
|
|
|
|
|
inline constexpr struct volt : named_unit<"V", watt / ampere> {} volt;
|
|
|
|
|
inline constexpr struct farad : named_unit<"F", coulomb / volt> {} farad;
|
|
|
|
|
inline constexpr struct ohm : named_unit<{u8"Ω", "ohm"}, volt / ampere> {} ohm;
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
=== "Prefixes"
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
template<PrefixableUnit auto U> struct micro_ : prefixed_unit<{u8"µ", "u"}, mag_power<10, -6>, U> {};
|
|
|
|
|
template<PrefixableUnit auto U> struct milli_ : prefixed_unit<"m", mag_power<10, -3>, U> {};
|
|
|
|
|
template<PrefixableUnit auto U> struct centi_ : prefixed_unit<"c", mag_power<10, -2>, U> {};
|
|
|
|
|
template<PrefixableUnit auto U> struct deci_ : prefixed_unit<"d", mag_power<10, -1>, U> {};
|
|
|
|
|
template<PrefixableUnit auto U> struct deca_ : prefixed_unit<"da", mag_power<10, 1>, U> {};
|
|
|
|
|
template<PrefixableUnit auto U> struct hecto_ : prefixed_unit<"h", mag_power<10, 2>, U> {};
|
|
|
|
|
template<PrefixableUnit auto U> struct kilo_ : prefixed_unit<"k", mag_power<10, 3>, U> {};
|
|
|
|
|
template<PrefixableUnit auto U> struct mega_ : prefixed_unit<"M", mag_power<10, 6>, U> {};
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
=== "Constants"
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
inline constexpr struct hyperfine_structure_transition_frequency_of_cs : named_unit<{u8"Δν_Cs", "dv_Cs"}, mag<9'192'631'770> * hertz> {} hyperfine_structure_transition_frequency_of_cs;
|
|
|
|
|
inline constexpr struct speed_of_light_in_vacuum : named_unit<"c", mag<299'792'458> * metre / second> {} speed_of_light_in_vacuum;
|
2024-04-19 15:29:00 +01:00
|
|
|
|
inline constexpr struct planck_constant : named_unit<"h", mag_ratio<662'607'015, 100'000'000> * mag_power<10, -34> * joule * second> {} planck_constant;
|
|
|
|
|
inline constexpr struct elementary_charge : named_unit<"e", mag_ratio<1'602'176'634, 1'000'000'000> * mag_power<10, -19> * coulomb> {} elementary_charge;
|
|
|
|
|
inline constexpr struct boltzmann_constant : named_unit<"k", mag_ratio<1'380'649, 1'000'000> * mag_power<10, -23> * joule / kelvin> {} boltzmann_constant;
|
|
|
|
|
inline constexpr struct avogadro_constant : named_unit<"N_A", mag_ratio<602'214'076, 100'000'000> * mag_power<10, 23> / mole> {} avogadro_constant;
|
2024-02-27 13:58:06 +01:00
|
|
|
|
inline constexpr struct luminous_efficacy : named_unit<"K_cd", mag<683> * lumen / watt> {} luminous_efficacy;
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
!!! important
|
|
|
|
|
|
|
|
|
|
Two symbols always have to be provided if the primary symbol contains characters outside of
|
|
|
|
|
the [basic literal character set](https://en.cppreference.com/w/cpp/language/charset).
|
|
|
|
|
The first must be provided as a UTF-8 literal and may contain any Unicode characters.
|
|
|
|
|
The second one must provide an alternative spelling and only use characters from within of
|
|
|
|
|
[basic literal character set](https://en.cppreference.com/w/cpp/language/charset).
|
|
|
|
|
|
|
|
|
|
!!! note
|
|
|
|
|
|
|
|
|
|
Unicode provides only a minimal set of characters available as subscripts, which are often used
|
|
|
|
|
to differentiate various constants and quantities of the same kind. To workaround this issue,
|
|
|
|
|
**mp-units** uses the '_' character to specify that the following characters should be considered
|
|
|
|
|
a subscript of the symbol.
|
|
|
|
|
|
|
|
|
|
!!! tip
|
|
|
|
|
|
2024-03-18 23:12:39 +09:00
|
|
|
|
For older compilers, it might be required to specify a `symbol_text` class explicitly
|
2024-02-27 13:58:06 +01:00
|
|
|
|
template name to initialize it with two symbols:
|
|
|
|
|
|
|
|
|
|
```cpp
|
2024-03-18 23:12:39 +09:00
|
|
|
|
inline constexpr struct ohm : named_unit<symbol_text{u8"Ω", "ohm"}, volt / ampere> {} ohm;
|
2024-02-27 13:58:06 +01:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Symbols for derived entities
|
|
|
|
|
|
|
|
|
|
### `text_encoding`
|
|
|
|
|
|
|
|
|
|
[ISQ](../../appendix/glossary.md#isq) and [SI](../../appendix/glossary.md#si) standards always
|
|
|
|
|
specify symbols using Unicode encoding. This is why it is a default and primary target for
|
|
|
|
|
text output. However, in some applications or environments, a standard ASCII-like text output
|
|
|
|
|
using only the characters from the [basic literal character set](https://en.cppreference.com/w/cpp/language/charset)
|
|
|
|
|
can be preferred by users.
|
|
|
|
|
|
|
|
|
|
This is why the library provides an option to change the default encoding to the ASCII one with:
|
2023-11-30 10:53:29 +01:00
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
enum class text_encoding : std::int8_t {
|
2024-02-27 13:58:06 +01:00
|
|
|
|
unicode, // µs; m³; L²MT⁻³
|
|
|
|
|
ascii, // us; m^3; L^2MT^-3
|
2023-11-30 10:53:29 +01:00
|
|
|
|
default_encoding = unicode
|
|
|
|
|
};
|
2024-02-27 13:58:06 +01:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Symbols of derived dimensions
|
|
|
|
|
|
|
|
|
|
#### `dimension_symbol_formatting`
|
|
|
|
|
|
|
|
|
|
`dimension_symbol_formatting` is a data type describing the configuration of the symbol generation
|
|
|
|
|
algorithm.
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
struct dimension_symbol_formatting {
|
|
|
|
|
text_encoding encoding = text_encoding::default_encoding;
|
|
|
|
|
};
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### `dimension_symbol()`
|
|
|
|
|
|
|
|
|
|
Returns a `std::string_view` with the symbol of a dimension for the provided configuration:
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
template<dimension_symbol_formatting fmt = dimension_symbol_formatting{}, typename CharT = char, Dimension D>
|
|
|
|
|
[[nodiscard]] consteval std::string_view dimension_symbol(D);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
For example:
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
static_assert(dimension_symbol<{.encoding = text_encoding::ascii}>(isq::power.dimension) == "L^2MT^-3");
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
!!! note
|
|
|
|
|
|
|
|
|
|
`std::string_view` is returned only when C++23 is available. Otherwise, an instance of a
|
|
|
|
|
`basic_fixed_string` is being returned.
|
2023-11-30 10:53:29 +01:00
|
|
|
|
|
2024-02-27 13:58:06 +01:00
|
|
|
|
#### `dimension_symbol_to()`
|
|
|
|
|
|
|
|
|
|
Inserts the generated dimension symbol into the output text iterator at runtime.
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
template<typename CharT = char, std::output_iterator<CharT> Out, Dimension D>
|
|
|
|
|
constexpr Out dimension_symbol_to(Out out, D d, dimension_symbol_formatting fmt = dimension_symbol_formatting{});
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
For example:
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
std::string txt;
|
|
|
|
|
dimension_symbol_to(std::back_inserter(txt), isq::power.dimension, {.encoding = text_encoding::ascii});
|
|
|
|
|
std::cout << txt << "\n";
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
The above prints:
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
L^2MT^-3
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### Symbols of derived units
|
|
|
|
|
|
|
|
|
|
#### `unit_symbol_formatting`
|
|
|
|
|
|
|
|
|
|
`unit_symbol_formatting` is a data type describing the configuration of the symbol generation
|
|
|
|
|
algorithm. It contains three orthogonal fields, each with a default value.
|
|
|
|
|
|
|
|
|
|
```cpp
|
2023-11-30 10:53:29 +01:00
|
|
|
|
enum class unit_symbol_solidus : std::int8_t {
|
|
|
|
|
one_denominator, // m/s; kg m⁻¹ s⁻¹
|
|
|
|
|
always, // m/s; kg/(m s)
|
|
|
|
|
never, // m s⁻¹; kg m⁻¹ s⁻¹
|
|
|
|
|
default_denominator = one_denominator
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
enum class unit_symbol_separator : std::int8_t {
|
|
|
|
|
space, // kg m²/s²
|
|
|
|
|
half_high_dot, // kg⋅m²/s² (valid only for unicode encoding)
|
|
|
|
|
default_separator = space
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct unit_symbol_formatting {
|
|
|
|
|
text_encoding encoding = text_encoding::default_encoding;
|
|
|
|
|
unit_symbol_solidus solidus = unit_symbol_solidus::default_denominator;
|
|
|
|
|
unit_symbol_separator separator = unit_symbol_separator::default_separator;
|
|
|
|
|
};
|
|
|
|
|
```
|
|
|
|
|
|
2024-02-27 13:58:06 +01:00
|
|
|
|
`unit_symbol_solidus` impacts how the division of unit symbols is being presented in the text
|
|
|
|
|
output. By default, the '/' will be printed if only one unit component is in the
|
|
|
|
|
denominator. Otherwise, the exponent syntax will be used.
|
|
|
|
|
|
|
|
|
|
`unit_symbol_separator` specifies how multiple multiplied units should be separated from each
|
|
|
|
|
other. By default, the space (' ') will be used as a separator.
|
|
|
|
|
|
|
|
|
|
#### `unit_symbol()`
|
2023-11-30 10:53:29 +01:00
|
|
|
|
|
|
|
|
|
Returns a `std::string_view` with the symbol of a unit for the provided configuration:
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
template<unit_symbol_formatting fmt = unit_symbol_formatting{}, typename CharT = char, Unit U>
|
2024-02-27 13:58:06 +01:00
|
|
|
|
[[nodiscard]] consteval std::string_view unit_symbol(U);
|
2023-11-30 10:53:29 +01:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
For example:
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
static_assert(unit_symbol<{.solidus = unit_symbol_solidus::never,
|
|
|
|
|
.separator = unit_symbol_separator::half_high_dot}>(kg * m / s2) == "kg⋅m⋅s⁻²");
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
!!! note
|
|
|
|
|
|
|
|
|
|
`std::string_view` is returned only when C++23 is available. Otherwise, an instance of a
|
2024-02-27 13:58:06 +01:00
|
|
|
|
`basic_fixed_string` is being returned. See more in the
|
|
|
|
|
[C++ compiler support](../../getting_started/installation_and_usage.md#static-constexpr-variables-in-constexpr-functions)
|
|
|
|
|
chapter.
|
2023-11-30 10:53:29 +01:00
|
|
|
|
|
2024-02-27 13:58:06 +01:00
|
|
|
|
#### `unit_symbol_to()`
|
2023-11-30 10:53:29 +01:00
|
|
|
|
|
2024-02-27 13:58:06 +01:00
|
|
|
|
Inserts the generated unit symbol into the output text iterator at runtime.
|
2023-11-30 10:53:29 +01:00
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
template<typename CharT = char, std::output_iterator<CharT> Out, Unit U>
|
|
|
|
|
constexpr Out unit_symbol_to(Out out, U u, unit_symbol_formatting fmt = unit_symbol_formatting{});
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
For example:
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
std::string txt;
|
|
|
|
|
unit_symbol_to(std::back_inserter(txt), kg * m / s2,
|
|
|
|
|
{.solidus = unit_symbol_solidus::never, .separator = unit_symbol_separator::half_high_dot});
|
|
|
|
|
std::cout << txt << "\n";
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
The above prints:
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
kg⋅m⋅s⁻²
|
|
|
|
|
```
|
|
|
|
|
|
2024-02-27 13:58:06 +01:00
|
|
|
|
## `space_before_unit_symbol` customization point
|
2023-09-04 11:09:40 +02:00
|
|
|
|
|
2023-09-29 11:21:27 +02:00
|
|
|
|
The [SI Brochure](../../appendix/references.md#SIBrochure) says:
|
2023-09-04 11:09:40 +02:00
|
|
|
|
|
|
|
|
|
!!! quote "SI Brochure"
|
|
|
|
|
|
|
|
|
|
The numerical value always precedes the unit and a space is always used to separate the unit from
|
|
|
|
|
the number. ... The only exceptions to this rule are for the unit symbols for degree, minute and
|
|
|
|
|
second for plane angle, `°`, `′` and `″`, respectively, for which no space is left between the
|
|
|
|
|
numerical value and the unit symbol.
|
|
|
|
|
|
2024-02-27 13:58:06 +01:00
|
|
|
|
There are more units with such properties. For example, percent (`%`) and per mille(`‰`).
|
|
|
|
|
|
|
|
|
|
To support the above and other similar cases, the library exposes `space_before_unit_symbol`
|
|
|
|
|
customization point. By default, its value is `true` for all the units, so the space between a number
|
|
|
|
|
and a unit will be inserted in the output text. To change this behavior, we have to provide a partial
|
|
|
|
|
specialization for a specific unit:
|
2023-09-04 11:09:40 +02:00
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
template<>
|
|
|
|
|
inline constexpr bool space_before_unit_symbol<non_si::degree> = false;
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
!!! note
|
|
|
|
|
|
2024-02-27 13:58:06 +01:00
|
|
|
|
The above works only for [the default formatting](#default-formatting) or for the format
|
|
|
|
|
strings that use `%?` placement field (`std::format("{}", q)` is equivalent to
|
|
|
|
|
`std::format("{:%N%?%U}", q)`).
|
2024-02-27 14:10:43 +01:00
|
|
|
|
|
2024-02-27 13:58:06 +01:00
|
|
|
|
In case a user provides custom format specification (e.g., `std::format("{:%N %U}", q)`),
|
|
|
|
|
the library will always obey this specification for all the units (no matter what the actual
|
|
|
|
|
value of the `space_before_unit_symbol` customization point is) and the separating space will always
|
|
|
|
|
be used in this case.
|
2023-09-04 11:09:40 +02:00
|
|
|
|
|
|
|
|
|
|
2024-02-27 13:58:06 +01:00
|
|
|
|
## Output streams
|
2023-07-24 17:36:49 +02:00
|
|
|
|
|
|
|
|
|
!!! tip
|
|
|
|
|
|
|
|
|
|
The output streaming support is opt-in and can be enabled by including the `<mp-units/ostream.h>`
|
|
|
|
|
header file.
|
|
|
|
|
|
2024-02-27 13:58:06 +01:00
|
|
|
|
The easiest way to print a dimension, unit, or quantity is to provide its object to the output stream:
|
2023-07-24 17:36:49 +02:00
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
const QuantityOf<isq::speed> auto v1 = avg_speed(220. * km, 2 * h);
|
|
|
|
|
const QuantityOf<isq::speed> auto v2 = avg_speed(140. * mi, 2 * h);
|
2024-02-27 13:58:06 +01:00
|
|
|
|
std::cout << v1 << '\n'; // 110 km/h
|
|
|
|
|
std::cout << v2 << '\n'; // 70 mi/h
|
|
|
|
|
std::cout << v2.unit << '\n'; // mi/h
|
|
|
|
|
std::cout << v2.dimension << '\n'; // LT⁻¹
|
2023-07-24 17:36:49 +02:00
|
|
|
|
```
|
|
|
|
|
|
2024-02-27 13:58:06 +01:00
|
|
|
|
The text output will always print the value using the default formatting for this entity.
|
2023-07-24 17:36:49 +02:00
|
|
|
|
|
2023-10-25 14:14:26 +02:00
|
|
|
|
!!! important "Important: Don't assume a unit"
|
2023-07-24 17:36:49 +02:00
|
|
|
|
|
2023-12-27 11:26:56 +01:00
|
|
|
|
Remember that when we deal with a quantity of an "unknown" (e.g., `auto`) type, it is a good
|
2023-10-25 14:14:26 +02:00
|
|
|
|
practice to always [convert the unit to the expected one](value_conversions.md#value-conversions)
|
2023-07-24 17:36:49 +02:00
|
|
|
|
before passing it to the text output:
|
|
|
|
|
|
|
|
|
|
```cpp
|
2023-09-13 10:44:50 +02:00
|
|
|
|
std::cout << v1.in(km / h) << '\n'; // 110 km/h
|
|
|
|
|
std::cout << v1.force_in(m / s) << '\n'; // 30.5556 m/s
|
2023-07-24 17:36:49 +02:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
2024-02-27 13:58:06 +01:00
|
|
|
|
### Output stream formatting
|
2023-07-24 17:36:49 +02:00
|
|
|
|
|
2023-12-27 11:34:06 +01:00
|
|
|
|
Only basic formatting can be applied to output streams. It includes control over width, fill,
|
2024-02-27 13:58:06 +01:00
|
|
|
|
and alignment.
|
|
|
|
|
|
|
|
|
|
The numerical value of the quantity will be printed according to the current stream state and standard
|
|
|
|
|
manipulators may be used to customize that (assuming that the underlying representation type
|
|
|
|
|
respects them).
|
2023-07-24 17:36:49 +02:00
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
std::cout << "|" << std::setw(10) << 123 * m << "|\n"; // | 123 m|
|
|
|
|
|
std::cout << "|" << std::setw(10) << std::left << 123 * m << "|\n"; // |123 m |
|
|
|
|
|
std::cout << "|" << std::setw(10) << std::setfill('*') << 123 * m << "|\n"; // |123 m*****|
|
|
|
|
|
```
|
|
|
|
|
|
2023-12-27 11:26:56 +01:00
|
|
|
|
!!! note
|
|
|
|
|
|
|
|
|
|
To have more control over the formatting of the quantity that is printed with the output
|
|
|
|
|
stream just use `std::cout << std::format(...)`.
|
|
|
|
|
|
2023-07-24 17:36:49 +02:00
|
|
|
|
|
2024-02-27 13:58:06 +01:00
|
|
|
|
## Text formatting
|
|
|
|
|
|
|
|
|
|
The library provides custom formatters for `std::format` facility, which allows fine-grained control
|
|
|
|
|
over what and how it is being printed in the text output.
|
2023-07-24 17:36:49 +02:00
|
|
|
|
|
|
|
|
|
!!! tip
|
|
|
|
|
|
|
|
|
|
The text formatting facility support is opt-in and can be enabled by including the
|
|
|
|
|
`<mp-units/format.h>` header file.
|
|
|
|
|
|
2024-02-27 13:58:06 +01:00
|
|
|
|
### Controlling width, fill, and alignment
|
|
|
|
|
|
|
|
|
|
Formatting grammar for all the entities provides control over width, fill, and alignment. The C++
|
|
|
|
|
standard grammar tokens `fill-and-align` and `width` are being used. They treat the entity as
|
|
|
|
|
a contiguous text to be aligned. For example, here are a few examples of the quantity numerical
|
|
|
|
|
value and symbol formatting:
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
std::println("|{:0}|", 123 * m); // |123 m|
|
|
|
|
|
std::println("|{:10}|", 123 * m); // | 123 m|
|
|
|
|
|
std::println("|{:<10}|", 123 * m); // |123 m |
|
|
|
|
|
std::println("|{:>10}|", 123 * m); // | 123 m|
|
|
|
|
|
std::println("|{:^10}|", 123 * m); // | 123 m |
|
|
|
|
|
std::println("|{:*<10}|", 123 * m); // |123 m*****|
|
|
|
|
|
std::println("|{:*>10}|", 123 * m); // |*****123 m|
|
|
|
|
|
std::println("|{:*^10}|", 123 * m); // |**123 m***|
|
2023-07-24 17:36:49 +02:00
|
|
|
|
```
|
|
|
|
|
|
2024-02-27 13:58:06 +01:00
|
|
|
|
It is important to note that in the second line above, the quantity text is aligned to
|
|
|
|
|
the right by default, which is consistent with the formatting of numeric types. Units and dimensions behave
|
|
|
|
|
as text and, thus, are aligned to the left by default.
|
|
|
|
|
|
|
|
|
|
!!! note
|
|
|
|
|
|
|
|
|
|
[`std::println` is a C++23 facility](https://en.cppreference.com/w/cpp/io/print). In case we
|
|
|
|
|
do not have access to C++23, we can obtain the same output with:
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
std::cout << std::format("<format-string>\n", <format-args>);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Dimension formatting
|
|
|
|
|
|
2024-05-05 18:58:40 +02:00
|
|
|
|
```ebnf
|
|
|
|
|
dimension-format-spec = [fill-and-align], [width], [dimension-spec];
|
|
|
|
|
dimension-spec = [text-encoding];
|
|
|
|
|
text-encoding = 'U' | 'A';
|
2024-02-27 13:58:06 +01:00
|
|
|
|
```
|
2023-07-24 17:36:49 +02:00
|
|
|
|
|
|
|
|
|
In the above grammar:
|
|
|
|
|
|
2024-02-27 13:58:06 +01:00
|
|
|
|
- `fill-and-align` and `width` tokens are defined in the [format.string.std](https://wg21.link/format.string.std)
|
2023-07-24 17:36:49 +02:00
|
|
|
|
chapter of the C++ standard specification,
|
2024-02-27 13:58:06 +01:00
|
|
|
|
- `text-encoding` token specifies the symbol text encoding:
|
|
|
|
|
- `U` (default) uses the **Unicode** symbols defined by [@ISO80000] (e.g., `LT⁻²`),
|
|
|
|
|
- `A` forces non-standard **ASCII**-only output (e.g., `LT^-2`).
|
|
|
|
|
|
|
|
|
|
Dimension symbols of some quantities are specified to use Unicode signs by the
|
|
|
|
|
[ISQ](../../appendix/glossary.md#isq) (e.g., `Θ` symbol for the _thermodynamic temperature_
|
|
|
|
|
dimension). The library follows this by default. From the engineering point of view, sometimes
|
|
|
|
|
Unicode text might not be the best solution, as terminals of many (especially embedded) devices
|
|
|
|
|
can output only letters from the basic literal character set. In such a case, the dimension
|
|
|
|
|
symbol can be forced to be printed using such characters thanks to `text-encoding` token:
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
std::println("{}", isq::dim_thermodynamic_temperature); // Θ
|
|
|
|
|
std::println("{:A}", isq::dim_thermodynamic_temperature); // O
|
|
|
|
|
std::println("{}", isq::power.dimension); // L²MT⁻³
|
|
|
|
|
std::println("{:A}", isq::power.dimension); // L^2MT^-3
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Unit formatting
|
|
|
|
|
|
2024-05-05 18:58:40 +02:00
|
|
|
|
```ebnf
|
|
|
|
|
unit-format-spec = [fill-and-align], [width], [unit-spec];
|
|
|
|
|
unit-spec = [text-encoding], [unit-symbol-solidus], [unit-symbol-separator], [L]
|
|
|
|
|
| [text-encoding], [unit-symbol-separator], [unit-symbol-solidus], [L]
|
|
|
|
|
| [unit-symbol-solidus], [text-encoding], [unit-symbol-separator], [L]
|
|
|
|
|
| [unit-symbol-solidus], [unit-symbol-separator], [text-encoding], [L]
|
|
|
|
|
| [unit-symbol-separator], [text-encoding], [unit-symbol-solidus], [L]
|
|
|
|
|
| [unit-symbol-separator], [unit-symbol-solidus], [text-encoding], [L];
|
|
|
|
|
unit-symbol-solidus = '1' | 'a' | 'n';
|
|
|
|
|
unit-symbol-separator = 's' | 'd';
|
2024-02-27 13:58:06 +01:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
In the above grammar:
|
|
|
|
|
|
|
|
|
|
- `fill-and-align` and `width` tokens are defined in the [format.string.std](https://wg21.link/format.string.std)
|
2023-07-24 17:36:49 +02:00
|
|
|
|
chapter of the C++ standard specification,
|
2024-02-27 13:58:06 +01:00
|
|
|
|
- `unit-symbol-solidus` token specifies how the division of units should look like:
|
|
|
|
|
- '1' (default) outputs `/` only when there is only **one** unit in the denominator, otherwise
|
2023-12-27 11:34:06 +01:00
|
|
|
|
negative exponents are printed (e.g., `m/s`, `kg m⁻¹ s⁻¹`)
|
2024-02-27 13:58:06 +01:00
|
|
|
|
- 'a' **always** uses solidus (e.g., `m/s`, `kg/(m s)`)
|
|
|
|
|
- 'n' **never** prints solidus, which means that negative exponents are always used
|
2023-12-27 11:34:06 +01:00
|
|
|
|
(e.g., `m s⁻¹`, `kg m⁻¹ s⁻¹`)
|
2024-02-27 13:58:06 +01:00
|
|
|
|
- `unit-symbol-separator` token specifies how multiplied unit symbols should be separated:
|
|
|
|
|
- 's' (default) uses **space** as a separator (e.g., `kg m²/s²`)
|
|
|
|
|
- 'd' uses half-high **dot** (`⋅`) as a separator (e.g., `kg⋅m²/s²`) (requires the Unicode encoding)
|
|
|
|
|
- 'L' is reserved for possible future localization use in case the C++ standard library gets access to
|
|
|
|
|
the ICU-like database.
|
|
|
|
|
|
|
|
|
|
!!! note
|
|
|
|
|
|
|
|
|
|
The above grammar intended that the elements of `unit-spec` can appear in
|
|
|
|
|
any order as they have unique characters. Users shouldn't have to remember the order of those tokens
|
|
|
|
|
to control the formatting of a unit symbol.
|
|
|
|
|
|
|
|
|
|
Unit symbols of some quantities are specified to use Unicode signs by the [SI](../../appendix/glossary.md#si)
|
|
|
|
|
(e.g., `Ω` symbol for the _resistance_ quantity). The library follows this by default. From the
|
|
|
|
|
engineering point of view, Unicode text might not be the best solution sometimes, as terminals
|
|
|
|
|
of many (especially embedded) devices can output only letters from the basic literal character set.
|
|
|
|
|
In such a case, the unit symbol can be forced to be printed using such characters thanks to
|
|
|
|
|
`text-encoding` token:
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
std::println("{}", si::ohm); // Ω
|
|
|
|
|
std::println("{:A}", si::ohm); // ohm
|
|
|
|
|
std::println("{}", us); // µs
|
|
|
|
|
std::println("{:A}", us); // us
|
|
|
|
|
std::println("{}", m / s2); // m/s²
|
|
|
|
|
std::println("{:A}", m / s2); // m/s^2
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Additionally, both ISO 80000 and [SI](../../appendix/glossary.md#si) leave some freedom on how to
|
|
|
|
|
print unit symbols. This is why two additional tokens were introduced.
|
|
|
|
|
|
|
|
|
|
`unit-symbol-solidus` specifies how the division of units should look like. By default,
|
|
|
|
|
`/` will be used only when the denominator contains only one unit. However, with the 'a' or 'n'
|
|
|
|
|
options, we can force the facility to print the `/` character always (even when there are more units
|
|
|
|
|
in the denominator), or never, in which case a parenthesis will be added to enclose all denominator
|
|
|
|
|
units.
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
std::println("{}", m / s); // m/s
|
|
|
|
|
std::println("{}", kg / m / s2); // kg m⁻¹ s⁻²
|
|
|
|
|
std::println("{:a}", m / s); // m/s
|
|
|
|
|
std::println("{:a}", kg / m / s2); // kg/(m s²)
|
|
|
|
|
std::println("{:n}", m / s); // m s⁻¹
|
|
|
|
|
std::println("{:n}", kg / m / s2); // kg m⁻¹ s⁻²
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Also, there are a few options to separate the units being multiplied. ISO 80000 (part 1) says:
|
|
|
|
|
|
|
|
|
|
!!! quote "ISO 80000-1"
|
|
|
|
|
|
|
|
|
|
When symbols for quantities are combined in a product of two or more quantities, this combination
|
|
|
|
|
is indicated in one of the following ways: `ab`, `a b`, `a · b`, `a × b`
|
2024-02-27 14:10:43 +01:00
|
|
|
|
|
2024-02-27 13:58:06 +01:00
|
|
|
|
_NOTE 1_ In some fields, e.g., vector algebra, distinction is made between `a ∙ b` and `a × b`.
|
|
|
|
|
|
|
|
|
|
The library supports `a b` and `a · b` only. Additionally, we decided that the extraneous space
|
|
|
|
|
in the latter case makes the result too verbose, so we decided just to use the `·` symbol as
|
|
|
|
|
a separator.
|
2023-07-24 17:36:49 +02:00
|
|
|
|
|
2024-02-27 13:58:06 +01:00
|
|
|
|
!!! note
|
|
|
|
|
|
|
|
|
|
Please let us know if you require more formatting options here.
|
|
|
|
|
|
|
|
|
|
The `unit-symbol-separator` token allows us to obtain the following outputs:
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
std::println("{}", kg * m2 / s2); // kg m²/s²
|
|
|
|
|
std::println("{:d}", kg * m2 / s2); // kg⋅m²/s²
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
!!! note
|
|
|
|
|
|
|
|
|
|
'd' requires the Unicode encoding to be set.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### Quantity formatting
|
|
|
|
|
|
2024-05-05 18:58:40 +02:00
|
|
|
|
```ebnf
|
|
|
|
|
quantity-format-spec = [fill-and-align], [width], [quantity-specs], [defaults-specs];
|
|
|
|
|
quantity-specs = conversion-spec;
|
|
|
|
|
| quantity-specs, conversion-spec;
|
|
|
|
|
| quantity-specs, literal-char;
|
|
|
|
|
literal-char = ? any character other than '{', '}', or '%' ?;
|
|
|
|
|
conversion-spec = '%', placement-type;
|
|
|
|
|
placement-type = subentity-id | '?' | '%';
|
|
|
|
|
defaults-specs = ':', default-spec-list;
|
|
|
|
|
default-spec-list = default-spec;
|
|
|
|
|
| default-spec-list, default-spec;
|
|
|
|
|
default-spec = subentity-id, '[' format-spec ']';
|
|
|
|
|
subentity-id = 'N' | 'U' | 'D';
|
|
|
|
|
format-spec = ? as specified by the formatter for the argument type ?;
|
2024-02-27 13:58:06 +01:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
In the above grammar:
|
|
|
|
|
|
|
|
|
|
- `fill-and-align` and `width` tokens are defined in the [format.string.std](https://wg21.link/format.string.std)
|
|
|
|
|
chapter of the C++ standard specification,
|
|
|
|
|
- `placement-type` token specifies which entity should be put and where:
|
|
|
|
|
- 'N' inserts a default-formatted numerical value of the quantity,
|
|
|
|
|
- 'U' inserts a default-formatted unit of the quantity,
|
|
|
|
|
- 'D' inserts a default-formatted dimension of the quantity,
|
|
|
|
|
- '?' inserts an optional separator between the number and a unit based on the value of
|
|
|
|
|
`space_before_unit_symbol` for this unit,
|
|
|
|
|
- '%' just inserts '%' character.
|
2024-04-18 22:55:19 +01:00
|
|
|
|
- `defaults-specs` token allows overwriting defaults for the underlying formatters with the custom
|
|
|
|
|
format string. Each override starts with a subentity identifier ('N', 'U', or 'D') followed by
|
|
|
|
|
the format string enclosed in square brackets.
|
2023-07-24 17:36:49 +02:00
|
|
|
|
|
2023-11-30 10:53:29 +01:00
|
|
|
|
#### Default formatting
|
2023-07-24 17:36:49 +02:00
|
|
|
|
|
2023-12-27 11:26:56 +01:00
|
|
|
|
To format `quantity` values, the formatting facility uses `quantity-format-spec`. If left empty,
|
2023-11-30 09:59:55 +01:00
|
|
|
|
the default formatting is applied. The same default formatting is also applied to the output streams.
|
|
|
|
|
This is why the following code lines produce the same output:
|
2023-07-24 17:36:49 +02:00
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
std::cout << "Distance: " << 123 * km << "\n";
|
|
|
|
|
std::cout << std::format("Distance: {}\n", 123 * km);
|
2024-02-27 13:58:06 +01:00
|
|
|
|
std::cout << std::format("Distance: {:%N%?%U}\n", 123 * km);
|
2023-07-24 17:36:49 +02:00
|
|
|
|
```
|
|
|
|
|
|
2023-11-30 09:59:55 +01:00
|
|
|
|
!!! note
|
|
|
|
|
|
2024-02-27 13:58:06 +01:00
|
|
|
|
For some quantities, the `{:%N %U}` format may provide a different output than the default one,
|
|
|
|
|
as some units have `space_before_unit_symbol` customization point explicitly set to `false`
|
|
|
|
|
(e.g., `%` and `°`).
|
2023-11-30 09:59:55 +01:00
|
|
|
|
|
|
|
|
|
|
2024-02-27 13:58:06 +01:00
|
|
|
|
#### Quantity numerical value, unit symbol, or both?
|
2023-07-24 17:36:49 +02:00
|
|
|
|
|
2024-02-27 13:58:06 +01:00
|
|
|
|
Thanks to the grammar provided above, the user can easily decide to either:
|
2023-07-24 17:36:49 +02:00
|
|
|
|
|
2024-02-27 13:58:06 +01:00
|
|
|
|
- print a whole quantity:
|
2023-07-24 17:36:49 +02:00
|
|
|
|
|
2024-02-27 13:58:06 +01:00
|
|
|
|
```cpp
|
|
|
|
|
std::println("Speed: {}", 120 * km / h);
|
|
|
|
|
```
|
2023-07-24 17:36:49 +02:00
|
|
|
|
|
2024-02-27 13:58:06 +01:00
|
|
|
|
```text
|
|
|
|
|
Speed: 120 km/h
|
|
|
|
|
```
|
2023-07-24 17:36:49 +02:00
|
|
|
|
|
2024-02-27 13:58:06 +01:00
|
|
|
|
- provide custom quantity formatting:
|
2023-08-03 21:23:34 +02:00
|
|
|
|
|
2023-07-24 17:36:49 +02:00
|
|
|
|
```cpp
|
2024-02-27 13:58:06 +01:00
|
|
|
|
std::println("Speed: {:%N in %U}", 120 * km / h);
|
2023-07-24 17:36:49 +02:00
|
|
|
|
```
|
|
|
|
|
|
2024-02-27 13:58:06 +01:00
|
|
|
|
```text
|
|
|
|
|
Speed: 120 in km/h
|
|
|
|
|
```
|
2023-07-24 17:36:49 +02:00
|
|
|
|
|
2024-02-27 13:58:06 +01:00
|
|
|
|
- provide custom formatting for components:
|
2023-07-24 17:36:49 +02:00
|
|
|
|
|
2024-02-27 13:58:06 +01:00
|
|
|
|
```cpp
|
2024-04-18 22:55:19 +01:00
|
|
|
|
std::println("Speed: {::N[.2f]U[n]}", 100. * km / (3 * h));
|
2024-02-27 13:58:06 +01:00
|
|
|
|
```
|
2023-07-24 17:36:49 +02:00
|
|
|
|
|
2024-02-27 13:58:06 +01:00
|
|
|
|
```text
|
|
|
|
|
Speed: 33.33 km h⁻¹
|
|
|
|
|
```
|
2023-07-24 17:36:49 +02:00
|
|
|
|
|
2024-02-27 13:58:06 +01:00
|
|
|
|
- print only specific components (numerical value, unit, or dimension):
|
2023-07-24 17:36:49 +02:00
|
|
|
|
|
2024-02-27 13:58:06 +01:00
|
|
|
|
```cpp
|
|
|
|
|
std::println("Speed:\n- number: {0:%N}\n- unit: {0:%U}\n- dimension: {0:%D}", 120 * km / h);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
Speed:
|
|
|
|
|
- number: 120
|
|
|
|
|
- unit: km/h
|
|
|
|
|
- dimension: LT⁻¹
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### Formatting of the quantity numerical value
|
|
|
|
|
|
|
|
|
|
The representation type used as a numerical value of a quantity must provide its own formatter
|
|
|
|
|
specialization. It will be called by the quantity formatter with the format-spec provided
|
2024-04-18 22:55:19 +01:00
|
|
|
|
by the user in the `N` defaults specification.
|
2024-02-27 13:58:06 +01:00
|
|
|
|
|
|
|
|
|
In case we use C++ fundamental arithmetic types with our quantities the standard formatter
|
|
|
|
|
specified in [format.string.std](https://wg21.link/format.string.std) will be used. The rest
|
|
|
|
|
of this chapter assumes that it is the case and provides some usage examples.
|
2023-07-24 17:36:49 +02:00
|
|
|
|
|
|
|
|
|
`sign` token allows us to specify how the value's sign is being printed:
|
|
|
|
|
|
|
|
|
|
```cpp
|
2024-04-18 22:55:19 +01:00
|
|
|
|
std::println("{0},{0::N[+]},{0::N[-]},{0::N[ ]}", 1 * m); // 1 m,+1 m,1 m, 1 m
|
|
|
|
|
std::println("{0},{0::N[+]},{0::N[-]},{0::N[ ]}", -1 * m); // -1 m,-1 m,-1 m,-1 m
|
2023-07-24 17:36:49 +02:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
where:
|
|
|
|
|
|
|
|
|
|
- `+` indicates that a sign should be used for both non-negative and negative numbers,
|
|
|
|
|
- `-` indicates that a sign should be used for negative numbers and negative zero only
|
|
|
|
|
(this is the default behavior),
|
|
|
|
|
- `<space>` indicates that a leading space should be used for non-negative numbers other
|
|
|
|
|
than negative zero, and a minus sign for negative numbers and negative zero.
|
|
|
|
|
|
|
|
|
|
`precision` token is allowed only for floating-point representation types:
|
|
|
|
|
|
|
|
|
|
```cpp
|
2024-04-18 22:55:19 +01:00
|
|
|
|
std::println("{::N[.0]}", 1.2345 * m); // 1 m
|
|
|
|
|
std::println("{::N[.1]}", 1.2345 * m); // 1 m
|
|
|
|
|
std::println("{::N[.2]}", 1.2345 * m); // 1.2 m
|
|
|
|
|
std::println("{::N[.3]}", 1.2345 * m); // 1.23 m
|
|
|
|
|
std::println("{::N[.0f]}", 1.2345 * m); // 1 m
|
|
|
|
|
std::println("{::N[.1f]}", 1.2345 * m); // 1.2 m
|
|
|
|
|
std::println("{::N[.2f]}", 1.2345 * m); // 1.23 m
|
2023-07-24 17:36:49 +02:00
|
|
|
|
```
|
|
|
|
|
|
2024-02-27 13:58:06 +01:00
|
|
|
|
`type` specifies how a value of the representation type is being printed.
|
2023-07-24 17:36:49 +02:00
|
|
|
|
For integral types:
|
|
|
|
|
|
|
|
|
|
```cpp
|
2024-04-18 22:55:19 +01:00
|
|
|
|
std::println("{::N[b]}", 42 * m); // 101010 m
|
|
|
|
|
std::println("{::N[B]}", 42 * m); // 101010 m
|
|
|
|
|
std::println("{::N[d]}", 42 * m); // 42 m
|
|
|
|
|
std::println("{::N[o]}", 42 * m); // 52 m
|
|
|
|
|
std::println("{::N[x]}", 42 * m); // 2a m
|
|
|
|
|
std::println("{::N[X]}", 42 * m); // 2A m
|
2023-07-24 17:36:49 +02:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
The above can be printed in an alternate version thanks to the `#` token:
|
|
|
|
|
|
|
|
|
|
```cpp
|
2024-04-18 22:55:19 +01:00
|
|
|
|
std::println("{::N[#b]}", 42 * m); // 0b101010 m
|
|
|
|
|
std::println("{::N[#B]}", 42 * m); // 0B101010 m
|
|
|
|
|
std::println("{::N[#o]}", 42 * m); // 052 m
|
|
|
|
|
std::println("{::N[#x]}", 42 * m); // 0x2a m
|
|
|
|
|
std::println("{::N[#X]}", 42 * m); // 0X2A m
|
2023-07-24 17:36:49 +02:00
|
|
|
|
```
|
|
|
|
|
|
2024-02-27 13:58:06 +01:00
|
|
|
|
For floating-point values, the `type` token works as follows:
|
2023-07-24 17:36:49 +02:00
|
|
|
|
|
|
|
|
|
```cpp
|
2024-04-18 22:55:19 +01:00
|
|
|
|
std::println("{::N[a]}", 1.2345678 * m); // 1.3c0ca2a5b1d5dp+0 m
|
|
|
|
|
std::println("{::N[.3a]}", 1.2345678 * m); // 1.3c1p+0 m
|
|
|
|
|
std::println("{::N[A]}", 1.2345678 * m); // 1.3C0CA2A5B1D5DP+0 m
|
|
|
|
|
std::println("{::N[.3A]}", 1.2345678 * m); // 1.3C1P+0 m
|
|
|
|
|
std::println("{::N[e]}", 1.2345678 * m); // 1.234568e+00 m
|
|
|
|
|
std::println("{::N[.3e]}", 1.2345678 * m); // 1.235e+00 m
|
|
|
|
|
std::println("{::N[E]}", 1.2345678 * m); // 1.234568E+00 m
|
|
|
|
|
std::println("{::N[.3E]}", 1.2345678 * m); // 1.235E+00 m
|
|
|
|
|
std::println("{::N[g]}", 1.2345678 * m); // 1.23457 m
|
|
|
|
|
std::println("{::N[g]}", 1.2345678e8 * m); // 1.23457e+08 m
|
|
|
|
|
std::println("{::N[.3g]}", 1.2345678 * m); // 1.23 m
|
|
|
|
|
std::println("{::N[.3g]}", 1.2345678e8 * m); // 1.23e+08 m
|
|
|
|
|
std::println("{::N[G]}", 1.2345678 * m); // 1.23457 m
|
|
|
|
|
std::println("{::N[G]}", 1.2345678e8 * m); // 1.23457E+08 m
|
|
|
|
|
std::println("{::N[.3G]}", 1.2345678 * m); // 1.23 m
|
|
|
|
|
std::println("{::N[.3G]}", 1.2345678e8 * m); // 1.23E+08 m
|
2023-07-24 17:36:49 +02:00
|
|
|
|
```
|