Comments (20)
Thanks @pieterderycke I appreciate it.
I need the decimal to support money calculations. double do not provide a good accuracy, and, depend on the calculations might yield less accurate results.
from jace.
@rcl2748 the need for Jace in our application got put on the backburner, so never got around to creating a proper pull request for this, but if creating a custom build is an option for you (rather than waiting for an updated NuGet package) then my branch contains fully working code for decimal support:
https://github.com/JulianRooze/Jace/tree/feature/decimal-support
Just clone and build and you should be good to go.
from jace.
It is possible, but it has quite some impact.
It is something that is already on my personal todo for sometime. But I did not yet found the time to start working on this.
from jace.
As I would like to use Jace for calculations involving money, decimal support is really important for me as well. I've begun with a really naive port of Jace where I simply cloned the project and started replacing "double" with "decimal" whenever I ran into it, but you quickly run into the code that emits the IL and there is no trivial way to replace the IL for doubles with IL for decimals because double is supported natively in IL while decimal is not so the IL is much more complicated (just emitting a constant is much harder). Maybe it's because I'm not very familiar with IL emission, but the easiest solution for me to this would be to use the .NET Expression API, which does natively support decimal, and compile an expression to a dynamic method.
I also don't know if it's feasible to make this change while also keeping double support. To me it seems like that wouldn't be really possible without introducing a secondary DecimalCalculationEngine
API for decimal. But that would at least allow you to reuse the existing parsing/AST building code.
EDIT: I see the DynamicCompiler
already uses the Expression API when compiled against NETFX_CORE.
from jace.
I will consider the support of adding decimal. But I need to investigate a clean way to offer both double and decimal support through the API. If you have an idea, please let me know. It is not an issue to support the necessary IL code. So don't worry about that aspect :-)
from jace.
Well, it might be nice to do something with generics. The public API of CalculationEngine can easily be made generic:
public interface ICalculationEngine<T>
{
void AddConstant(string constantName, T value);
void AddFunction(string functionName, Func<T, T, T, T, T, T, T> function);
void AddFunction(string functionName, Func<T, T, T, T, T, T> function);
void AddFunction(string functionName, Func<T, T, T, T, T> function);
void AddFunction(string functionName, Func<T, T, T, T> function);
void AddFunction(string functionName, Func<T, T, T> function);
void AddFunction(string functionName, Func<T, T> function);
void AddFunction(string functionName, Func<T> function);
Func<System.Collections.Generic.Dictionary<string, T>, T> Build(string formulaText);
T Calculate(string formulaText);
T Calculate(string formulaText, System.Collections.Generic.IDictionary<string, T> variables);
Jace.Execution.FormulaBuilder Formula(string formulaText);
}
Of course, for backwards compatibility, you still want CalculationEngine
to refer to the one that takes and returns doubles. Naming the decimal one the DecimalCalculationEngine
is okay, but then maybe introduce some kind of other entry point that let's you say "I want a calculation engine for double/decimal". Something like:
public static class CalculationEngineFactory
{
public static ICalculationEngine<T> Create<T>()
{
..
}
}
from jace.
Just a quick update on this. I went ahead and tried to make Jace work with both double as well as decimal. This is by no means a "please merge this" yet (it's a pull request for my own fork anyway ;)), more of a proof of concept.
For the most part, it was a matter of turning classes that depended on double
into classes with generics. For the code generation I've only implemented the code gen via de Expressions API, not through IL emit.
Using the decimal support now involves creating a DecimalCalculationEngine
which is perhaps not that elegant. The CalculationEngine could possibly implement both ICalculationEngine<double>
as well as ICalculationEngine<decimal>
but there would be a hiding/clashing implementation of these two interface methods:
Jace.Execution.FormulaBuilder<T> Formula(string formulaText);
T Calculate(string formulaText);
Since they would differ only by return type, which wouldn't work.
For our own internal purposes for Jace, my changes are 'good enough' but I'd be happy to work on making it mergeable back to master.
There's probably some unnecessary code duplication still, especially the decimal interpreter is just a copy-paste of the double interpreter. I'll see if I can unify these again. Because there's no generics support for operators this would require adding an abstraction for additional/multiplication/etc, marginally slowing down the interpreter.
from jace.
Thanks for the suggested modfications. I will have a more detailed look at your code this weekend. I like the idea, I only don't like the code duplication... ;-)
from jace.
Agreed, so I just updated the code ;)
I got rid of the duplication with the interpreter by doing what I said in my last comment.
Also, I added some comments to the pull request to clarify/justify some of the code I've changed.
My eye also caught this other issue that was opened:
It's probably pretty trivial to add BigInteger support to Jace now. The only real hurdle I see is the IL emit support. I don't want to dictate how you write your code of course, but isn't the Expression API pretty widely available on platforms now and couldn't you make it the default instead of IL emit and use that as a fallback only? Just an idea :)
from jace.
Have you had a chance to look over my suggested changes yet? :)
Like I said, for us the changes I've made work perfectly fine and are 'good enough', but of course it'd be nice if they could some day be contributed back to master.
Additionally, in the meantime I've mostly implemented BigInteger support as a proof of concept in very few lines of code and in a single file and it seems to work fine (aside from parts of the expression generator that rely on Math
which of course has no overloads for BigInteger, so I need to add an abstraction there still). I've created a new project within the solution for it, as it adds a reliance on the System.Numerics assembly and it'd be a separate NuGet package as well.
Again, that's leaving aside the IL generation bits, which are just too scary for me ;)
from jace.
Sorry for the (very) late response :-)
We should pull your changes back in the master of Jace. Support for decimal and BigInteger would be an interesting feature for Jace.
And don't be afraid of the IL generation. I think we could better drop it. It is only required for older platforms such as Windows Phone 7. And support for these platforms can be easily dropped. So we can simplify the source code of Jace by doing that.
from jace.
Only just noticed your response! Sorry for my late response now ;)
That'd be great! I'll try to make my code ready for a pull request in the next few days. The BigInteger code isn't ready yet, but the decimal code is. I'll try to add tests for it first though.
from jace.
Can you please add this feature. We are still waiting for it :)
from jace.
Hi, any progress on decimal support? I've tried using @JulianRooze branch, but unfortunately some tests are failing on this branch.
For example: CalculationEngineTests -> TestFormulaBuilder():
[TestMethod]
public void TestFormulaBuilder()
{
DecimalCalculationEngine engine = new DecimalCalculationEngine();
Func<int, decimal, decimal> function = (Func<int, decimal, decimal>)engine.Formula("var1+2*(3*age)")
.Parameter("var1", DataType.Integer)
.Parameter("age", DataType.FloatingPoint)
.Result(DataType.FloatingPoint)
.Build();
decimal result = function(2, 4m);
Assert.AreEqual(26.0m, result);
}
With test result:
Message: Assert.AreEqual failed. Expected:<26.0>. Actual:<35936165692946818613102097204>.
from jace.
Hello @mesika I could look to bring proper support to the official version of Jace. But it was never a high priority for me, because double was good-enough for me. In which context would you require decimal support?
from jace.
Hi @mesika ,
I am also interested in support decimal for money calculation.
Looks like that NCalc supports it
Be careful, I haven't tested it yet.
Anyway, thank you @pieterderycke for your library.
from jace.
Hi!
Like Julian I need decimal support. So I've just updated Julian's solution of decimal's support.
All doubles tests are passing but need to create some tests for decimals calculations too.
https://github.com/mrxrsd/Jace/tree/feature/decimal-support-updated
I forgot to updated TokenReader, decimals version is not working yet.
from jace.
100% passed in all tests (double and decimal).
I've replicated all double's tests with the new decimal engine.
from jace.
@mrxrsd thanks for the work on supporting Decimal - we'd really like to have this vetted and moved to the main build of Jace. Seeing as how it was originally called out as going to be supported with 1.0, is there any ETA on a proper merge and release with decimal support? @pieterderycke
from jace.
@mrxrsd thanks for the work on supporting Decimal - we'd really like to have this vetted and moved to the main build of Jace. Seeing as how it was originally called out as going to be supported with 1.0, is there any ETA on a proper merge and release with decimal support? @pieterderycke
You can check my repository: https://github.com/mrxrsd/jace
This feature and others fixes are merged there but I never publish a nuget package by my own.
from jace.
Related Issues (20)
- Can we make Random overrideable? HOT 3
- Bitwise operations
- Non base-10 numbers
- Matrix & display function itself
- Override operators HOT 2
- Feature Request: Option to set calc trigonomic functions with degrees (not radian) HOT 1
- Wrong precendence for unitary minus and exponential
- Invalid floating point numbers cause InvalidOperationException
- Problems with ambiguity of e
- Invalid scientific notation leads to IndexOutOfBoundsException instead of ParseException
- Upgrade to NetStandard 2.0 HOT 2
- Interpreter.BuildFormula does not work with constants
- Is this project still being updated? HOT 2
- Runtime Error : Could not load file or assembly System.Runtime HOT 2
- JaceOptions case sensitivity does not get applied to FunctionRegistry or ConstantRegistry on engine constructor HOT 4
- Bug in operators precedence HOT 17
- Request for dynamic variables
- PEMDAS HOT 2
- Introducing _sonic_, a maintained Jace.NET fork/successor HOT 1
- avg function not working HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from jace.