Double Precision Settings

In DICOM standard, the DS (Decimal String) Value Representation stores numerical values as strings, limited to 16 bytes. This constraint means full double precision often cannot be preserved. DicomObjects provides two configuration settings to help manage this:

  • DicomGlobal.PreserveDoublePrecision
  • DicomGlobal.DoublePrecisionDSAttributes

These settings determine how closely double values are preserved when writing to DS attributes within DICOM’s constraints.

How These Settings Work Together

PreserveDoublePrecision DoublePrecisionDSAttributes Behaviour
false anything No double precision is preserved for DS attributes.
true empty Double precision is preserved for all DS attributes.
true non-empty list Double precision is preserved only for attributes in the list.

Platform-Specific Behaviour

The behaviour of double precision handling in DS attributes differs depending on the version of the DicomObjects library used.


DicomObjects for .NET Framework (8.40 / 8.48)

  • Throws DicomValidationException for strings > 16 bytes.
  • Rounding may seem inconsistent with double inputs over 15–17 significant digits due to the precision limit of the double type. Values beyond this are auto-rounded by .NET runtime before DicomObjects receives them.
  • Input value -0.0 is stored and displayed as “0”.

DicomObjects for .NET Core / .NET (Core 3 / 5 / 8 / NetStandard 2.0)

  • Throws ValidationException instead of DicomValidationException for strings > 16 bytes.
  • Rounds consistently when compared to .NET Framework.
  • Input value -0.0 is stored and displayed as “-0”.
  • Higher precision for byte[] inputs regardless of PreserveDoublePrecision, and for double inputs when PreserveDoublePrecision is false.

Data Processing Behaviour

Depending on the data type used to assign values to DS attributes, behaviour varies:

1. Assigning a double

When PreserveDoublePrecision = true:

  • The value is rounded or truncated to fit within 16 bytes.
  • Scientific notation is avoided.

When PreserveDoublePrecision = false:

  • Scientific notation is used for very large or small numbers.
  • Results are usually rounded to 7 to 8 significant digits. .NET Framework preserves 7 significant digits and .NET Core 3.0+ up to 8 except in special cases such as double.MaxValue double.MinValue or infinity.

Examples Results (PreserveDoublePrecision = true)

Input .NET Framework Core 3+
12345678.123456789"12345678.1234568"
-12345678.123456789"-12345678.123456"
0.00000000012345"0.00000000012345"
123456789"123456789"
-123456789"-123456789"
-0.012345678901234567"-0.0123456789012"
-123456789012345"-123456789012345"
12345678901234569"1234567890123456"
123456789012345696"1234567890123457""1234567890123456"
123456789012345655"1234567890123456"
double.MaxValue / double.PositiveInfinity"9999999999999999"
double.MinValue/ double.NegativeInfinity"-999999999999999"
double.NaNnull
0"0"
-0.0"0""-0"

Examples Results (PreserveDoublePrecision = false)

Input .NET Framework Core 3+
12345678.123456789"1.234568E+07""12345678"
-12345678.123456789"-1.234568E+07""-12345678"
0.00000000012345"1.2345E-10"
123456789"1.234568E+08""123456790"
-123456789"-1.234568E+08""-123456790"
12345678901234569"1.234568E+16""1.2345678E+16"
-123456789012345"-1.234568E+14""-1.2345679E+14"
1234.56789"1234.568""1234.5679"
1.23456789111111"1.234568""1.2345679"
-0.012345678901234567"-0.01234568""-0.012345679"
0.0"0"
-0.0"0""-0"
double.MaxValue / double.PositiveInfinity"9999999999999999"
double.MinValue/ double.NegativeInfinity"-999999999999999"
double.NaNnull

2. Assigning a string

Precision settings and the .NET runtime version do not affect string inputs.

  • Strings ≤ 16 bytes are accepted as-is.
  • Strings > 16 bytes raise a DicomValidationException or ValidationException.
  • Scientific notation is allowed if it fits.

Example Results

Input .NET Framework Core 3+
"12345678.123456789"DicomValidationExceptionValidationException
"-12345678.123456789"DicomValidationExceptionValidationException
"12345678901234569"DicomValidationExceptionValidationException
"123456789""123456789"
"-123456789""-123456789"
"-123456789012345""-123456789012345"
"1234.56789""1234.56789"
"1.23456789111111""1.23456789111111"
"0.00000000012345""0.00000000012345"
"-0.0123456789012""-0.0123456789012"
"0.0""0.0"
"-0.0""-0.0"
"1.23e-4""1.23e-4"

3. Assigning a byte[]

Precision settings do not affect byte array input. The final value stored in the attribute is mainly affected by how the double is converted to a byte array before assigning it to the attribute.

The following example results’ inputs are based on convert a double value to string using ToString(), then convert it to byte array. The rounding/truncation already happened in the .ToString() before assigning byte array to attribute.

Example Code

double val = 12345678.123456789;
string ss = val.ToString();
byte[] bytes = Encoding.ASCII.GetBytes(ss);
dataSet.Add(Keyword.PatientSize, val);

Examples Results

Input .NET Framework Core 3+
12345678.123456789"12345678.1234568""12345678.12345679"
-12345678.123456789"-12345678.1234568""-12345678.12345679"
123456789"123456789"
-123456789"-123456789"
12345678901234569"1.23456789012346E+16""12345678901234568"
-123456789012345"-123456789012345"
1234.56789"1234.56789"
1.23456789111111"1.23456789111111"
0.00000000012345"1.2345E-10"
-0.0123456789012"-0.0123456789012"
0.0"0"
-0.0"0""-0"
double.MaxValue"1.79769313486232E+308""1.7976931348623157E+308"
double.MinValue"-1.79769313486232E+308""-1.7976931348623157E+308"
double.NaN"NaN"