xtquant.xtbson.bson36.decimal128

Tools for working with the BSON decimal128 type.

New in version 3.4.

The Decimal128 BSON type requires MongoDB 3.4+.
  1# Copyright 2016-present MongoDB, Inc.
  2#
  3# Licensed under the Apache License, Version 2.0 (the "License");
  4# you may not use this file except in compliance with the License.
  5# You may obtain a copy of the License at
  6#
  7# http://www.apache.org/licenses/LICENSE-2.0
  8#
  9# Unless required by applicable law or agreed to in writing, software
 10# distributed under the License is distributed on an "AS IS" BASIS,
 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12# See the License for the specific language governing permissions and
 13# limitations under the License.
 14
 15"""Tools for working with the BSON decimal128 type.
 16
 17.. versionadded:: 3.4
 18
 19.. note:: The Decimal128 BSON type requires MongoDB 3.4+.
 20"""
 21
 22import decimal
 23import struct
 24import sys
 25
 26_PACK_64 = struct.Struct("<Q").pack
 27_UNPACK_64 = struct.Struct("<Q").unpack
 28
 29_EXPONENT_MASK = 3 << 61
 30_EXPONENT_BIAS = 6176
 31_EXPONENT_MAX = 6144
 32_EXPONENT_MIN = -6143
 33_MAX_DIGITS = 34
 34
 35_INF = 0x7800000000000000
 36_NAN = 0x7C00000000000000
 37_SNAN = 0x7E00000000000000
 38_SIGN = 0x8000000000000000
 39
 40_NINF = (_INF + _SIGN, 0)
 41_PINF = (_INF, 0)
 42_NNAN = (_NAN + _SIGN, 0)
 43_PNAN = (_NAN, 0)
 44_NSNAN = (_SNAN + _SIGN, 0)
 45_PSNAN = (_SNAN, 0)
 46
 47_CTX_OPTIONS = {
 48    "prec": _MAX_DIGITS,
 49    "rounding": decimal.ROUND_HALF_EVEN,
 50    "Emin": _EXPONENT_MIN,
 51    "Emax": _EXPONENT_MAX,
 52    "capitals": 1,
 53    "flags": [],
 54    "traps": [decimal.InvalidOperation, decimal.Overflow, decimal.Inexact],
 55    "clamp": 1,
 56}
 57
 58_DEC128_CTX = decimal.Context(**_CTX_OPTIONS.copy())
 59
 60
 61def create_decimal128_context():
 62    """Returns an instance of :class:`decimal.Context` appropriate
 63    for working with IEEE-754 128-bit decimal floating point values.
 64    """
 65    opts = _CTX_OPTIONS.copy()
 66    opts["traps"] = []
 67    return decimal.Context(**opts)
 68
 69
 70def _decimal_to_128(value):
 71    """Converts a decimal.Decimal to BID (high bits, low bits).
 72
 73    :Parameters:
 74      - `value`: An instance of decimal.Decimal
 75    """
 76    with decimal.localcontext(_DEC128_CTX) as ctx:
 77        value = ctx.create_decimal(value)
 78
 79    if value.is_infinite():
 80        return _NINF if value.is_signed() else _PINF
 81
 82    sign, digits, exponent = value.as_tuple()
 83
 84    if value.is_nan():
 85        if digits:
 86            raise ValueError("NaN with debug payload is not supported")
 87        if value.is_snan():
 88            return _NSNAN if value.is_signed() else _PSNAN
 89        return _NNAN if value.is_signed() else _PNAN
 90
 91    significand = int("".join([str(digit) for digit in digits]))
 92    bit_length = significand.bit_length()
 93
 94    high = 0
 95    low = 0
 96    for i in range(min(64, bit_length)):
 97        if significand & (1 << i):
 98            low |= 1 << i
 99
100    for i in range(64, bit_length):
101        if significand & (1 << i):
102            high |= 1 << (i - 64)
103
104    biased_exponent = exponent + _EXPONENT_BIAS
105
106    if high >> 49 == 1:
107        high = high & 0x7FFFFFFFFFFF
108        high |= _EXPONENT_MASK
109        high |= (biased_exponent & 0x3FFF) << 47
110    else:
111        high |= biased_exponent << 49
112
113    if sign:
114        high |= _SIGN
115
116    return high, low
117
118
119class Decimal128(object):
120    """BSON Decimal128 type::
121
122      >>> Decimal128(Decimal("0.0005"))
123      Decimal128('0.0005')
124      >>> Decimal128("0.0005")
125      Decimal128('0.0005')
126      >>> Decimal128((3474527112516337664, 5))
127      Decimal128('0.0005')
128
129    :Parameters:
130      - `value`: An instance of :class:`decimal.Decimal`, string, or tuple of
131        (high bits, low bits) from Binary Integer Decimal (BID) format.
132
133    .. note:: :class:`~Decimal128` uses an instance of :class:`decimal.Context`
134      configured for IEEE-754 Decimal128 when validating parameters.
135      Signals like :class:`decimal.InvalidOperation`, :class:`decimal.Inexact`,
136      and :class:`decimal.Overflow` are trapped and raised as exceptions::
137
138        >>> Decimal128(".13.1")
139        Traceback (most recent call last):
140          File "<stdin>", line 1, in <module>
141          ...
142        decimal.InvalidOperation: [<class 'decimal.ConversionSyntax'>]
143        >>>
144        >>> Decimal128("1E-6177")
145        Traceback (most recent call last):
146          File "<stdin>", line 1, in <module>
147          ...
148        decimal.Inexact: [<class 'decimal.Inexact'>]
149        >>>
150        >>> Decimal128("1E6145")
151        Traceback (most recent call last):
152          File "<stdin>", line 1, in <module>
153          ...
154        decimal.Overflow: [<class 'decimal.Overflow'>, <class 'decimal.Rounded'>]
155
156      To ensure the result of a calculation can always be stored as BSON
157      Decimal128 use the context returned by
158      :func:`create_decimal128_context`::
159
160        >>> import decimal
161        >>> decimal128_ctx = create_decimal128_context()
162        >>> with decimal.localcontext(decimal128_ctx) as ctx:
163        ...     Decimal128(ctx.create_decimal(".13.3"))
164        ...
165        Decimal128('NaN')
166        >>>
167        >>> with decimal.localcontext(decimal128_ctx) as ctx:
168        ...     Decimal128(ctx.create_decimal("1E-6177"))
169        ...
170        Decimal128('0E-6176')
171        >>>
172        >>> with decimal.localcontext(DECIMAL128_CTX) as ctx:
173        ...     Decimal128(ctx.create_decimal("1E6145"))
174        ...
175        Decimal128('Infinity')
176
177      To match the behavior of MongoDB's Decimal128 implementation
178      str(Decimal(value)) may not match str(Decimal128(value)) for NaN values::
179
180        >>> Decimal128(Decimal('NaN'))
181        Decimal128('NaN')
182        >>> Decimal128(Decimal('-NaN'))
183        Decimal128('NaN')
184        >>> Decimal128(Decimal('sNaN'))
185        Decimal128('NaN')
186        >>> Decimal128(Decimal('-sNaN'))
187        Decimal128('NaN')
188
189      However, :meth:`~Decimal128.to_decimal` will return the exact value::
190
191        >>> Decimal128(Decimal('NaN')).to_decimal()
192        Decimal('NaN')
193        >>> Decimal128(Decimal('-NaN')).to_decimal()
194        Decimal('-NaN')
195        >>> Decimal128(Decimal('sNaN')).to_decimal()
196        Decimal('sNaN')
197        >>> Decimal128(Decimal('-sNaN')).to_decimal()
198        Decimal('-sNaN')
199
200      Two instances of :class:`Decimal128` compare equal if their Binary
201      Integer Decimal encodings are equal::
202
203        >>> Decimal128('NaN') == Decimal128('NaN')
204        True
205        >>> Decimal128('NaN').bid == Decimal128('NaN').bid
206        True
207
208      This differs from :class:`decimal.Decimal` comparisons for NaN::
209
210        >>> Decimal('NaN') == Decimal('NaN')
211        False
212    """
213
214    __slots__ = ("__high", "__low")
215
216    _type_marker = 19
217
218    def __init__(self, value):
219        if isinstance(value, (str, decimal.Decimal)):
220            self.__high, self.__low = _decimal_to_128(value)
221        elif isinstance(value, (list, tuple)):
222            if len(value) != 2:
223                raise ValueError(
224                    "Invalid size for creation of Decimal128 "
225                    "from list or tuple. Must have exactly 2 "
226                    "elements."
227                )
228            self.__high, self.__low = value
229        else:
230            raise TypeError("Cannot convert %r to Decimal128" % (value,))
231
232    def to_decimal(self):
233        """Returns an instance of :class:`decimal.Decimal` for this
234        :class:`Decimal128`.
235        """
236        high = self.__high
237        low = self.__low
238        sign = 1 if (high & _SIGN) else 0
239
240        if (high & _SNAN) == _SNAN:
241            return decimal.Decimal((sign, (), "N"))
242        elif (high & _NAN) == _NAN:
243            return decimal.Decimal((sign, (), "n"))
244        elif (high & _INF) == _INF:
245            return decimal.Decimal((sign, (), "F"))
246
247        if (high & _EXPONENT_MASK) == _EXPONENT_MASK:
248            exponent = ((high & 0x1FFFE00000000000) >> 47) - _EXPONENT_BIAS
249            return decimal.Decimal((sign, (0,), exponent))
250        else:
251            exponent = ((high & 0x7FFF800000000000) >> 49) - _EXPONENT_BIAS
252
253        arr = bytearray(15)
254        mask = 0x00000000000000FF
255        for i in range(14, 6, -1):
256            arr[i] = (low & mask) >> ((14 - i) << 3)
257            mask = mask << 8
258
259        mask = 0x00000000000000FF
260        for i in range(6, 0, -1):
261            arr[i] = (high & mask) >> ((6 - i) << 3)
262            mask = mask << 8
263
264        mask = 0x0001000000000000
265        arr[0] = (high & mask) >> 48
266
267        # cdecimal only accepts a tuple for digits.
268        digits = tuple(int(digit) for digit in str(int.from_bytes(arr, "big")))
269
270        with decimal.localcontext(_DEC128_CTX) as ctx:
271            return ctx.create_decimal((sign, digits, exponent))
272
273    @classmethod
274    def from_bid(cls, value):
275        """Create an instance of :class:`Decimal128` from Binary Integer
276        Decimal string.
277
278        :Parameters:
279          - `value`: 16 byte string (128-bit IEEE 754-2008 decimal floating
280            point in Binary Integer Decimal (BID) format).
281        """
282        if not isinstance(value, bytes):
283            raise TypeError("value must be an instance of bytes")
284        if len(value) != 16:
285            raise ValueError("value must be exactly 16 bytes")
286        return cls((_UNPACK_64(value[8:])[0], _UNPACK_64(value[:8])[0]))
287
288    @property
289    def bid(self):
290        """The Binary Integer Decimal (BID) encoding of this instance."""
291        return _PACK_64(self.__low) + _PACK_64(self.__high)
292
293    def __str__(self):
294        dec = self.to_decimal()
295        if dec.is_nan():
296            # Required by the drivers spec to match MongoDB behavior.
297            return "NaN"
298        return str(dec)
299
300    def __repr__(self):
301        return "Decimal128('%s')" % (str(self),)
302
303    def __setstate__(self, value):
304        self.__high, self.__low = value
305
306    def __getstate__(self):
307        return self.__high, self.__low
308
309    def __eq__(self, other):
310        if isinstance(other, Decimal128):
311            return self.bid == other.bid
312        return NotImplemented
313
314    def __ne__(self, other):
315        return not self == other
def create_decimal128_context():
62def create_decimal128_context():
63    """Returns an instance of :class:`decimal.Context` appropriate
64    for working with IEEE-754 128-bit decimal floating point values.
65    """
66    opts = _CTX_OPTIONS.copy()
67    opts["traps"] = []
68    return decimal.Context(**opts)

Returns an instance of decimal.Context appropriate for working with IEEE-754 128-bit decimal floating point values.

class Decimal128:
120class Decimal128(object):
121    """BSON Decimal128 type::
122
123      >>> Decimal128(Decimal("0.0005"))
124      Decimal128('0.0005')
125      >>> Decimal128("0.0005")
126      Decimal128('0.0005')
127      >>> Decimal128((3474527112516337664, 5))
128      Decimal128('0.0005')
129
130    :Parameters:
131      - `value`: An instance of :class:`decimal.Decimal`, string, or tuple of
132        (high bits, low bits) from Binary Integer Decimal (BID) format.
133
134    .. note:: :class:`~Decimal128` uses an instance of :class:`decimal.Context`
135      configured for IEEE-754 Decimal128 when validating parameters.
136      Signals like :class:`decimal.InvalidOperation`, :class:`decimal.Inexact`,
137      and :class:`decimal.Overflow` are trapped and raised as exceptions::
138
139        >>> Decimal128(".13.1")
140        Traceback (most recent call last):
141          File "<stdin>", line 1, in <module>
142          ...
143        decimal.InvalidOperation: [<class 'decimal.ConversionSyntax'>]
144        >>>
145        >>> Decimal128("1E-6177")
146        Traceback (most recent call last):
147          File "<stdin>", line 1, in <module>
148          ...
149        decimal.Inexact: [<class 'decimal.Inexact'>]
150        >>>
151        >>> Decimal128("1E6145")
152        Traceback (most recent call last):
153          File "<stdin>", line 1, in <module>
154          ...
155        decimal.Overflow: [<class 'decimal.Overflow'>, <class 'decimal.Rounded'>]
156
157      To ensure the result of a calculation can always be stored as BSON
158      Decimal128 use the context returned by
159      :func:`create_decimal128_context`::
160
161        >>> import decimal
162        >>> decimal128_ctx = create_decimal128_context()
163        >>> with decimal.localcontext(decimal128_ctx) as ctx:
164        ...     Decimal128(ctx.create_decimal(".13.3"))
165        ...
166        Decimal128('NaN')
167        >>>
168        >>> with decimal.localcontext(decimal128_ctx) as ctx:
169        ...     Decimal128(ctx.create_decimal("1E-6177"))
170        ...
171        Decimal128('0E-6176')
172        >>>
173        >>> with decimal.localcontext(DECIMAL128_CTX) as ctx:
174        ...     Decimal128(ctx.create_decimal("1E6145"))
175        ...
176        Decimal128('Infinity')
177
178      To match the behavior of MongoDB's Decimal128 implementation
179      str(Decimal(value)) may not match str(Decimal128(value)) for NaN values::
180
181        >>> Decimal128(Decimal('NaN'))
182        Decimal128('NaN')
183        >>> Decimal128(Decimal('-NaN'))
184        Decimal128('NaN')
185        >>> Decimal128(Decimal('sNaN'))
186        Decimal128('NaN')
187        >>> Decimal128(Decimal('-sNaN'))
188        Decimal128('NaN')
189
190      However, :meth:`~Decimal128.to_decimal` will return the exact value::
191
192        >>> Decimal128(Decimal('NaN')).to_decimal()
193        Decimal('NaN')
194        >>> Decimal128(Decimal('-NaN')).to_decimal()
195        Decimal('-NaN')
196        >>> Decimal128(Decimal('sNaN')).to_decimal()
197        Decimal('sNaN')
198        >>> Decimal128(Decimal('-sNaN')).to_decimal()
199        Decimal('-sNaN')
200
201      Two instances of :class:`Decimal128` compare equal if their Binary
202      Integer Decimal encodings are equal::
203
204        >>> Decimal128('NaN') == Decimal128('NaN')
205        True
206        >>> Decimal128('NaN').bid == Decimal128('NaN').bid
207        True
208
209      This differs from :class:`decimal.Decimal` comparisons for NaN::
210
211        >>> Decimal('NaN') == Decimal('NaN')
212        False
213    """
214
215    __slots__ = ("__high", "__low")
216
217    _type_marker = 19
218
219    def __init__(self, value):
220        if isinstance(value, (str, decimal.Decimal)):
221            self.__high, self.__low = _decimal_to_128(value)
222        elif isinstance(value, (list, tuple)):
223            if len(value) != 2:
224                raise ValueError(
225                    "Invalid size for creation of Decimal128 "
226                    "from list or tuple. Must have exactly 2 "
227                    "elements."
228                )
229            self.__high, self.__low = value
230        else:
231            raise TypeError("Cannot convert %r to Decimal128" % (value,))
232
233    def to_decimal(self):
234        """Returns an instance of :class:`decimal.Decimal` for this
235        :class:`Decimal128`.
236        """
237        high = self.__high
238        low = self.__low
239        sign = 1 if (high & _SIGN) else 0
240
241        if (high & _SNAN) == _SNAN:
242            return decimal.Decimal((sign, (), "N"))
243        elif (high & _NAN) == _NAN:
244            return decimal.Decimal((sign, (), "n"))
245        elif (high & _INF) == _INF:
246            return decimal.Decimal((sign, (), "F"))
247
248        if (high & _EXPONENT_MASK) == _EXPONENT_MASK:
249            exponent = ((high & 0x1FFFE00000000000) >> 47) - _EXPONENT_BIAS
250            return decimal.Decimal((sign, (0,), exponent))
251        else:
252            exponent = ((high & 0x7FFF800000000000) >> 49) - _EXPONENT_BIAS
253
254        arr = bytearray(15)
255        mask = 0x00000000000000FF
256        for i in range(14, 6, -1):
257            arr[i] = (low & mask) >> ((14 - i) << 3)
258            mask = mask << 8
259
260        mask = 0x00000000000000FF
261        for i in range(6, 0, -1):
262            arr[i] = (high & mask) >> ((6 - i) << 3)
263            mask = mask << 8
264
265        mask = 0x0001000000000000
266        arr[0] = (high & mask) >> 48
267
268        # cdecimal only accepts a tuple for digits.
269        digits = tuple(int(digit) for digit in str(int.from_bytes(arr, "big")))
270
271        with decimal.localcontext(_DEC128_CTX) as ctx:
272            return ctx.create_decimal((sign, digits, exponent))
273
274    @classmethod
275    def from_bid(cls, value):
276        """Create an instance of :class:`Decimal128` from Binary Integer
277        Decimal string.
278
279        :Parameters:
280          - `value`: 16 byte string (128-bit IEEE 754-2008 decimal floating
281            point in Binary Integer Decimal (BID) format).
282        """
283        if not isinstance(value, bytes):
284            raise TypeError("value must be an instance of bytes")
285        if len(value) != 16:
286            raise ValueError("value must be exactly 16 bytes")
287        return cls((_UNPACK_64(value[8:])[0], _UNPACK_64(value[:8])[0]))
288
289    @property
290    def bid(self):
291        """The Binary Integer Decimal (BID) encoding of this instance."""
292        return _PACK_64(self.__low) + _PACK_64(self.__high)
293
294    def __str__(self):
295        dec = self.to_decimal()
296        if dec.is_nan():
297            # Required by the drivers spec to match MongoDB behavior.
298            return "NaN"
299        return str(dec)
300
301    def __repr__(self):
302        return "Decimal128('%s')" % (str(self),)
303
304    def __setstate__(self, value):
305        self.__high, self.__low = value
306
307    def __getstate__(self):
308        return self.__high, self.__low
309
310    def __eq__(self, other):
311        if isinstance(other, Decimal128):
312            return self.bid == other.bid
313        return NotImplemented
314
315    def __ne__(self, other):
316        return not self == other

BSON Decimal128 type::

>>> Decimal128(Decimal("0.0005"))
Decimal128('0.0005')
>>> Decimal128("0.0005")
Decimal128('0.0005')
>>> Decimal128((3474527112516337664, 5))
Decimal128('0.0005')

:Parameters:

  • value: An instance of decimal.Decimal, string, or tuple of (high bits, low bits) from Binary Integer Decimal (BID) format.
~Decimal128 uses an instance of decimal.Context

configured for IEEE-754 Decimal128 when validating parameters. Signals like decimal.InvalidOperation, decimal.Inexact, and decimal.Overflow are trapped and raised as exceptions::

>>> Decimal128(".13.1")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  ...
decimal.InvalidOperation: [<class 'decimal.ConversionSyntax'>]
>>>
>>> Decimal128("1E-6177")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  ...
decimal.Inexact: [<class 'decimal.Inexact'>]
>>>
>>> Decimal128("1E6145")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  ...
decimal.Overflow: [<class 'decimal.Overflow'>, <class 'decimal.Rounded'>]

To ensure the result of a calculation can always be stored as BSON Decimal128 use the context returned by create_decimal128_context()::

>>> import decimal
>>> decimal128_ctx = create_decimal128_context()
>>> with decimal.localcontext(decimal128_ctx) as ctx:
...     Decimal128(ctx.create_decimal(".13.3"))
...
Decimal128('NaN')
>>>
>>> with decimal.localcontext(decimal128_ctx) as ctx:
...     Decimal128(ctx.create_decimal("1E-6177"))
...
Decimal128('0E-6176')
>>>
>>> with decimal.localcontext(DECIMAL128_CTX) as ctx:
...     Decimal128(ctx.create_decimal("1E6145"))
...
Decimal128('Infinity')

To match the behavior of MongoDB's Decimal128 implementation str(Decimal(value)) may not match str(Decimal128(value)) for NaN values::

>>> Decimal128(Decimal('NaN'))
Decimal128('NaN')
>>> Decimal128(Decimal('-NaN'))
Decimal128('NaN')
>>> Decimal128(Decimal('sNaN'))
Decimal128('NaN')
>>> Decimal128(Decimal('-sNaN'))
Decimal128('NaN')

However, ~Decimal128.to_decimal() will return the exact value::

>>> Decimal128(Decimal('NaN')).to_decimal()
Decimal('NaN')
>>> Decimal128(Decimal('-NaN')).to_decimal()
Decimal('-NaN')
>>> Decimal128(Decimal('sNaN')).to_decimal()
Decimal('sNaN')
>>> Decimal128(Decimal('-sNaN')).to_decimal()
Decimal('-sNaN')

Two instances of Decimal128 compare equal if their Binary Integer Decimal encodings are equal::

>>> Decimal128('NaN') == Decimal128('NaN')
True
>>> Decimal128('NaN').bid == Decimal128('NaN').bid
True

This differs from decimal.Decimal comparisons for NaN::

>>> Decimal('NaN') == Decimal('NaN')
False
Decimal128(value)
219    def __init__(self, value):
220        if isinstance(value, (str, decimal.Decimal)):
221            self.__high, self.__low = _decimal_to_128(value)
222        elif isinstance(value, (list, tuple)):
223            if len(value) != 2:
224                raise ValueError(
225                    "Invalid size for creation of Decimal128 "
226                    "from list or tuple. Must have exactly 2 "
227                    "elements."
228                )
229            self.__high, self.__low = value
230        else:
231            raise TypeError("Cannot convert %r to Decimal128" % (value,))
def to_decimal(self):
233    def to_decimal(self):
234        """Returns an instance of :class:`decimal.Decimal` for this
235        :class:`Decimal128`.
236        """
237        high = self.__high
238        low = self.__low
239        sign = 1 if (high & _SIGN) else 0
240
241        if (high & _SNAN) == _SNAN:
242            return decimal.Decimal((sign, (), "N"))
243        elif (high & _NAN) == _NAN:
244            return decimal.Decimal((sign, (), "n"))
245        elif (high & _INF) == _INF:
246            return decimal.Decimal((sign, (), "F"))
247
248        if (high & _EXPONENT_MASK) == _EXPONENT_MASK:
249            exponent = ((high & 0x1FFFE00000000000) >> 47) - _EXPONENT_BIAS
250            return decimal.Decimal((sign, (0,), exponent))
251        else:
252            exponent = ((high & 0x7FFF800000000000) >> 49) - _EXPONENT_BIAS
253
254        arr = bytearray(15)
255        mask = 0x00000000000000FF
256        for i in range(14, 6, -1):
257            arr[i] = (low & mask) >> ((14 - i) << 3)
258            mask = mask << 8
259
260        mask = 0x00000000000000FF
261        for i in range(6, 0, -1):
262            arr[i] = (high & mask) >> ((6 - i) << 3)
263            mask = mask << 8
264
265        mask = 0x0001000000000000
266        arr[0] = (high & mask) >> 48
267
268        # cdecimal only accepts a tuple for digits.
269        digits = tuple(int(digit) for digit in str(int.from_bytes(arr, "big")))
270
271        with decimal.localcontext(_DEC128_CTX) as ctx:
272            return ctx.create_decimal((sign, digits, exponent))

Returns an instance of decimal.Decimal for this Decimal128.

@classmethod
def from_bid(cls, value):
274    @classmethod
275    def from_bid(cls, value):
276        """Create an instance of :class:`Decimal128` from Binary Integer
277        Decimal string.
278
279        :Parameters:
280          - `value`: 16 byte string (128-bit IEEE 754-2008 decimal floating
281            point in Binary Integer Decimal (BID) format).
282        """
283        if not isinstance(value, bytes):
284            raise TypeError("value must be an instance of bytes")
285        if len(value) != 16:
286            raise ValueError("value must be exactly 16 bytes")
287        return cls((_UNPACK_64(value[8:])[0], _UNPACK_64(value[:8])[0]))

Create an instance of Decimal128 from Binary Integer Decimal string.

:Parameters:

  • value: 16 byte string (128-bit IEEE 754-2008 decimal floating point in Binary Integer Decimal (BID) format).
bid

The Binary Integer Decimal (BID) encoding of this instance.