#1 2025-01-17 21:22:15

mvg7
Member
Registered: 2021-10-03
Posts: 12

varCurrency is a bit confusing

Hi!
As I understand, since mormot 2 can convert values to varCurrency, unlike Mormot 1, this code wont work If system's decimail separator set as comma:

  
  var APrice: double;
  ToDouble(_JsonFastFloat('{"price": 0.156}').price, APrice);

Im mormot 1 it was like

  
    if AllowVarDouble then
      typ := TextToVariantNumberType(JSON) else
      typ := TextToVariantNumberTypeNoDouble(JSON);

and with delphi's FormatSettings.DecimalSeparator:='.'; the code above worked

Is there any option to prevent the mormot from generating varCurrency ?

Offline

#2 2025-01-17 21:40:20

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,793
Website

Re: varCurrency is a bit confusing

I don't understand what you write, because mORMot does not at all take into account FormatSettings.

Offline

#3 2025-01-17 22:58:44

mvg7
Member
Registered: 2021-10-03
Posts: 12

Re: varCurrency is a bit confusing

ab wrote:

I don't understand what you write, because mORMot does not at all take into account FormatSettings.

I write that I would expect APrice =  0.156 in this code:

ToDouble(_JsonFastFloat('{"price": 0.156}').price, APrice);

However actually APrice is not  0.156 in Mormot 2.

Offline

#4 2025-01-18 08:45:34

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,793
Website

Re: varCurrency is a bit confusing

You are a bit confused for sure. Your analysis is not accurate.
Note first that the 0.156 is stored as varCurrency into the TDocVariant, not as varDouble, because there is less than 5 decimals.
In that respect, mORMot 1 and mORMot 2 are the same.

Then why are you using ToDouble()?
It makes an implicit conversion to string, which is not what we expect here, and produces a wrong result.

The following is simple and works well:

APrice := _JsonFastFloat('{"price": 0.156}').price;

See https://github.com/synopse/mORMot2/commit/869c6aee7

Offline

#5 2025-01-18 12:04:09

mvg7
Member
Registered: 2021-10-03
Posts: 12

Re: varCurrency is a bit confusing

ab wrote:

Note first that the 0.156 is stored as varCurrency into the TDocVariant, not as varDouble, because there is less than 5 decimals.
In that respect, mORMot 1 and mORMot 2 are the same.

Sorry but they are not the same, at least my old SynCommons version of 2020:)
This old version in function GetNumericVariantFromJSON first checked

if AllowVarDouble then
      typ := TextToVariantNumberType(JSON)

and didnt try to produce varCurrency, the value {"price": 0.156} was varDouble.

Now what is confusing:

  var s1, s2: string;
  s1 := _JsonFastFloat('{"price": 0.156}').price; // result is '0,156'
  s2 := _JsonFastFloat('{"price": 0.15678}').price; // result is '0.15678'

depending on decimals count, result's format is different!

Since ToDouble accepts decimal dot as separator, internal conversion varDouble to string also uses decimal dot, one can expect that decimal separator for value {"price": 0.156} is also dot and not comma.

The idea that confusing me is that I was thinkng that when working with mormot, we can assume that decimal separator is dot and dont rely on system settings.

Last edited by mvg7 (2025-01-18 12:15:17)

Offline

#6 2025-01-18 17:49:22

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,793
Website

Re: varCurrency is a bit confusing

This is how it works with any variant, when you assign a variant (like the "price" function) to a string.
It is not part of mORMot.

Offline

#7 2025-01-18 20:36:08

mvg7
Member
Registered: 2021-10-03
Posts: 12

Re: varCurrency is a bit confusing

ab wrote:

This is how it works with any variant, when you assign a variant (like the "price" function) to a string.
It is not part of mORMot.

Ok! I just beg you to try do do something with it! Like some new TDocVariantOption "dvoPreferDoubleValue"

Like this...

  else if not dvoPreferDoubleValue and (frac < 0) and  // please no varCurrency!:)))  
          (frac >= -4) then       
  begin
    // currency as ###.0123
    TSynVarData(Value).VType := varCurrency;
    Value.VInt64 := v64 * CURRENCY_FACTOR[frac]; // as round(CurrValue*10000)
  end
  else if AllowVarDouble and
          (frac > -324) then // 5.0 x 10^-324 .. 1.7 x 10^308

Offline

#8 2025-01-18 21:47:15

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,793
Website

Re: varCurrency is a bit confusing

If you use mORMot VariantToDouble() function you have the proper support and no problem.

The issue comes from your side, using transient string values.

Offline

#9 2025-01-19 11:16:42

mvg7
Member
Registered: 2021-10-03
Posts: 12

Re: varCurrency is a bit confusing

ab wrote:

If you use mORMot VariantToDouble() function you have the proper support and no problem.

Indeed! Many thanks, best support ever!!

Offline

Board footer

Powered by FluxBB