Skip to content

Commit

Permalink
Fixed issue with Decimal String conversion resulting in more than 16 … (
Browse files Browse the repository at this point in the history
#367)

* Fixed issue with Decimal String conversion resulting in more than 16 characters.

* Added documentation and one more test case.
  • Loading branch information
rvantklooster authored Oct 6, 2023
1 parent f00a0d3 commit 3f3b8ad
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 5 deletions.
34 changes: 29 additions & 5 deletions src/ValueRepresentation.js
Original file line number Diff line number Diff line change
Expand Up @@ -533,13 +533,37 @@ class DecimalString extends AsciiStringRepresentation {
}

formatValue(value) {
if (value === null) {
return "";
}
if (value === null) return "";

const str = String(value);
let str = String(value);
if (str.length > this.maxLength) {
return value.toExponential();
// Characters needed for '-' at start.
const sign_chars = value < 0 ? 1 : 0;

// Decide whether to use scientific notation.
const logval = Math.log10(Math.abs(value));

// Numbers larger than 1e14 cannot be correctly represented by truncating
// their string representations to 16 chars, e.g pi * 10^13 would become
// '314159265358979.', which may not be universally understood. This limit
// is 1e13 for negative numbers because of the minus sign.
// For negative exponents, the point of equal precision between scientific
// and standard notation is 1e-4 e.g. '0.00031415926535' and
// '3.1415926535e-04' are both 16 chars.
const use_scientific = logval < -4 || logval >= 14 - sign_chars;
if (use_scientific) {
const trunc_str = value.toExponential(16 - sign_chars);
if (trunc_str.length <= 16) return trunc_str;
// If string is too long, correct the length.
return value.toExponential(
16 - (trunc_str.length - 16) - sign_chars
);
} else {
const trunc_str = value.toFixed(16 - sign_chars);
if (trunc_str.length <= 16) return trunc_str;
// If string is too long, correct the length.
return value.toFixed(16 - sign_chars - (trunc_str.length - 16));
}
}
return str;
}
Expand Down
24 changes: 24 additions & 0 deletions test/data.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import datasetWithNullNumberVRs from "./mocks/null_number_vrs_dataset.json";
import { rawTags } from "./rawTags";

import { EXPLICIT_LITTLE_ENDIAN, IMPLICIT_LITTLE_ENDIAN } from "./../src/constants/dicom.js";
import { ValueRepresentation } from "../src/ValueRepresentation";

const {
DicomMetaDictionary,
Expand Down Expand Up @@ -790,4 +791,27 @@ it("Tests that reading fails on a DICOM without a meta length tag", () => {
}).toThrow(
"Invalid DICOM file, meta length tag is malformed or not present."
);
});

it.each([
[1.0, "1"],
[0.0, "0"],
[-0.0, "0"],
[0.123, "0.123"],
[-0.321, "-0.321"],
[0.00001, "0.00001"],
[3.14159265358979323846, "3.14159265358979"],
[-3.14159265358979323846, "-3.1415926535898"],
[5.3859401928763739403e-7, "5.38594019288e-7"],
[-5.3859401928763739403e-7, "-5.3859401929e-7"],
[1.2342534378125532912998323e10, "12342534378.1255"],
[6.40708699858767842501238e13, "64070869985876.8"],
[1.7976931348623157e308, "1.797693135e+308"],
[0.99990081787109, "0.99990081787109"],
])
("A converted decimal string should not exceed 16 bytes in length", (a, expected) => {
const decimalString = ValueRepresentation.createByTypeString("DS");
let value = decimalString.formatValue(a);
expect(value.length).toBeLessThanOrEqual(16);
expect(value).toBe(expected);
});

0 comments on commit 3f3b8ad

Please sign in to comment.