Convertir punto flotante de Python en decimal de C#

CorePress2024-01-25  13

Estoy intentando convertir un número de punto flotante en Python a decimal en C# usando pythonnet.

Digamos que hay un número 0,0234337688540165776476565071.

He probado esto de dos maneras:

usando flotador()

from System import Decimal
Decimal(0.0234337688540165776476565071)
# Same with Decimal(float(0.0234337688540165776476565071))

0.02343377

usando Python Decimal nativo

from System import Decimal
from decimal import Decimal as PyDecimal
Decimal(PyDecimal("0.0234337688540165776476565071"))

# This loses every number under the floating-point
0

¿Qué debo hacer?

El valor devuelto por PyDecimal("0.0234337688540165776476565071") es un decimal. ¿Por qué pones Decimal() junto a los resultados? Si desea mayor precisión, utilice Doble. Un Double tiene 64 bits, mientras que un Float tiene 32 bits. Delawarecimal ofrece una mayor precisión que flotante con 32 bits para la mayoría de los números porque utiliza un algoritmo lorítmico. Double and Float utiliza un algoritmo exponencial

- jdweng

28/03/2021 a las 13:36

El PyDecimal anterior es del tipo nativo de Python y estoy intentando convertir el decimal de Python en System.Decimal de C#. Por eso hice Decimal(PyDecimal(0.212....)).

-6991httam

28/03/2021 a las 17:58

¿Por qué Python Decimal sería diferente de Ne3 Decimal? Ambos son IEEE 754. Consulte: en.wikipedia.org/wiki/Decimal_floating_point

- jdweng

29 de marzo de 2021 a las 0:28



------------------------------------

A partir de los ejemplos de su pregunta, parece que está intentando convertir una cadena a System.Decimal. Para eso, System.Decimal tiene un método Parse:

from System import Decimal

Decimal.Parse("0.0234337688540165776476565071")

Nota: probablemente también necesites pasar CultureInfo.InvariantCulture dependiendo de tu escenario.

1

¡Esto es realmente simple y funciona para mí! ¡Gracias! Por qué no sabía esto...Parse()

-6991httam

29/03/2021 a las 14:44



------------------------------------

Si conviertes una cadena en un flotante de Python, se truncará a 64 bits y perderás precisión. Tendrás que utilizar un constructor diferente para System.Decimal. Por ejemplo:

public Decimal (int lo, int mid, int hi, bool isNegative, byte scale);

Omitir la validación, podría verse así

from System import Decimal
from System import Int32, Boolean, Byte

def str_to_csp_decimal(number: str) -> Decimal:
    """ convert a string to a C# Decimal """
    is_negative = number[0] == "-"
    abs_value = number[1:] if is_negative else number

    has_fraction = "." in abs_value 
    if has_fraction:
        integer, fraction = abs_value.split(".")
        scale = len(fraction)                # denominator = 10 ** scale
        numerator = int(integer + fraction)  # no precision loss for integers
    else:
        scale = 0                            # denominator == 1
        numerator = int(abs_value)
    
    assert numerator < (2 << 96), "Decimal only has 96 bits of precision"

    # split the numerator into the lower, mid, and high 32 bits
    mask = 0xFFFFFFFF
    low = Int32(numerator & mask)
    mid = Int32((numerator >> 32) & mask)
    high = Int32((numerator >> 64) & mask)

    return Decimal(low, mid, high, Boolean(is_negative), Byte(scale))

str_to_csp_decimal("0.0234337688540165776476565071").ToString()

2

¿Por qué no utilizar simplemente el método Decimal.Parse?

-PERDIDO

28/03/2021 a las 20:00

Tu respuesta también es sorprendente. Muchas gracias por esto.

-6991httam

29/03/2021 a las 14:43

Su guía para un futuro mejor - libreflare
Su guía para un futuro mejor - libreflare