Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a literal notation for decimal in IronPython?

suppose I have the following IronPython script:

def Calculate(input):
    return input * 1.21

When called from C# with a decimal, this function returns a double:

var python = Python.CreateRuntime();
dynamic engine = python.UseFile("mypythonscript.py")

decimal input = 100m; // input is of type Decimal
// next line throws RuntimeBinderException: 
//     "cannot implicitly convert double to decimal"
decimal result = engine.Calculate(input); 

I seem to have two options:

First, I could cast at the C# side: seems like a no-go as I might loose precision.

decimal result = (decimal)engine.Calculate(input); 

Second option is to use System.Decimal in the python script: works, but pollutes the script somewhat...

from System import *

def CalculateVAT(amount):
    return amount * Decimal(1.21)

Is there a short-hand notation DLR that the number 1.21 should be interpreted as a Decimal, much like I would use the '1.21m' notation in C#? Or is there any other way to enforce decimal to be used instead of double?

like image 663
jeroenh Avatar asked Apr 09 '10 08:04

jeroenh


People also ask

What is a decimal literal Python?

The Python "SyntaxError: invalid decimal literal" occurs when we declare a variable with a name that starts with a digit. To solve the error, start the variable name with a letter or an underscore as variable names cannot start with numbers. Here is an example of how the error occurs.

Does Python have a decimal type?

A new module, decimal, was added to Python's standard library. It contains two classes, Decimal and Context. Decimal instances represent numbers, and Context instances are used to wrap up various settings such as the precision and default rounding mode.


2 Answers

Look at the python docs:

Decimal instances can be constructed from integers, strings, or tuples. To create a Decimal from a float, first convert it to a string. This serves as an explicit reminder of the details of the conversion (including representation error).

Unfortunatelly there is no short hand notation you are looking for. Even python has none. The standard way of 'hard coding' a decimal is to pass a string representation to the decimal constructor:

from decimal import Decimal
my_decimal = Decimal("1.21")

If you are writing code that is heavy on .net interop passing (it seems like you are) it may be better just using the .net Decimal datatype right away, as you proposed yourself. However be aware that you passing a floating point number to the decimal constructor in this example. You may get a small error in accuracy from the conversion, if the number has much more decimal places:

from System import *
my_decimal = Decimal(1.21)

So you may be better off using this constructor overload:

from System import *
my_decimal = Decimal(121, 0, 0, False, 2)

Not the most beautiful and shortest way of doing what you want, but the best in terms of performance and accuracy.

like image 190
Philip Daubmeier Avatar answered Oct 17 '22 23:10

Philip Daubmeier


seems like a no-go as I might lose precision.

Yeah, you do that in the other method too:

Decimal(1.21)

Once you've written 1.21 that's a floating point number and you've already lost the full precision before even passing it to the Decimal constructor. That's why Python's native Decimal class must be initialised from a string, not a float:

decimal.Decimal('1.21')

There doesn't seem to be a similar constructor for .NET's Decimal, but you could perhaps do it using the constituent parts constructor:

System.Decimal(121, 0, 0, False, 2)
like image 28
bobince Avatar answered Oct 17 '22 21:10

bobince