Problem with PadL() and REAL8 parameter ?

This forum is meant for questions and discussions about the X# language and tools
Post Reply
AlainC
Posts: 10
Joined: Mon Nov 15, 2021 9:57 am

Problem with PadL() and REAL8 parameter ?

Post by AlainC »

Hello,

I have a problem with the return of the PadL() function:
LOCAL c AS STRING
LOCAL i AS REAL8
i := 5
c := PadL(i, 2, "0") // => "5," instead of "05"

If "i" is typed DWORD then PadL() return "05" as expected.
LOCAL c AS STRING
LOCAL i AS DWORD
i := 5
c := PadL(i, 2, "0") // => "05" ok

Do you have the same result ?

XSharp 2.13.2.2, Dialect VO, Properties : all options are checked

Regards
Alain
ic2
Posts: 1858
Joined: Sun Feb 28, 2016 11:30 pm
Location: Holland

Problem with PadL() and REAL8 parameter ?

Post by ic2 »

Hello Alain,
AlainC post=24330 userid=6561 wrote: I have a problem with the return of the PadL() function:
c := PadL(i, 2, "0") // => "5," instead of "05"

Do you have the same result ?
I tried it in my X# 2.12 and also in VO, both have the same result. When I change the 2nd parameter to 4 I get 5,00.

So I think that with a Real8 as uValue, PadL first expands the number of decimals when nLength is increased.

Dick
FFF
Posts: 1584
Joined: Fri Sep 25, 2015 4:52 pm
Location: Germany

Problem with PadL() and REAL8 parameter ?

Post by FFF »

Alain,
yes. That said, i never realized, i could "pad" non strings ;-)
Seems, Real8, Real4, Double, Single are broken, while Float works as expected.
Regards
Karl
(on Win8.1/64, Xide32 2.20, X#2.20.0.3)
User avatar
Chris
Posts: 4929
Joined: Thu Oct 08, 2015 7:48 am
Location: Greece

Problem with PadL() and REAL8 parameter ?

Post by Chris »

Hi Alain,

It's as Dick said, a floating point value is first converted to its string representation, following the same rules that Str() uses, using the number of decimal points specified with SetDecimal(). It's the same as in VO.
Chris Pyrgas

XSharp Development Team
chris(at)xsharp.eu
AlainC
Posts: 10
Joined: Mon Nov 15, 2021 9:57 am

Problem with PadL() and REAL8 parameter ?

Post by AlainC »

Hello everyone,

OK, I understand. We learn every day ! Float seems to follow the same rules.

Alain
FFF
Posts: 1584
Joined: Fri Sep 25, 2015 4:52 pm
Location: Germany

Problem with PadL() and REAL8 parameter ?

Post by FFF »

Chris,
why does it work with FLOAT?
Regards
Karl
(on Win8.1/64, Xide32 2.20, X#2.20.0.3)
Jamal
Posts: 322
Joined: Mon Jul 03, 2017 7:02 pm

Problem with PadL() and REAL8 parameter ?

Post by Jamal »

The problem seems to be internal to the PadL function which in turn calls Ntrim(uValue). The NTrim seems to be the culprit.
I created a PadL2() from the X# PadL() so you can see the issue and workaround by using:
ret := uValue:ToString() instead of ret := Ntrim(uValue)

Also, note that Real8 value is actually 5.00 not 5 and the length of the variable is 4 not 1.
FLOAT value is 5 and has no decimal point and length is 1. That's why the code works with FLOAT not REAL8 since your are PADL to a length of 2. Watch the variables in the VS debugger to see their value representations.

Robert: Just a suggestion: C# will not let assign you a value like that with no decimal points. May X# can do a compiler check to prevent such ambiguity and assumptions.

Code: Select all

USING System
USING System.Collections.Generic
USING System.Linq
USING System.Text

FUNCTION Start() AS VOID STRICT
    LOCAL c AS STRING
    LOCAL i AS real8
    i := 5
    c := PadL2(i, 2, "0")    // => "05"
    
    
    Console.WriteLine(c) 
    Console.ReadKey()
RETURN 
FUNCTION PadL2( uValue AS USUAL, nLength AS INT, cFillChar := " " AS STRING ) AS STRING
    // If they send in an empty string then change to " "
    IF cFillChar == NULL .OR. cFillChar :Length == 0
        cFillChar := " "
    ENDIF
    LOCAL ret AS STRING
    IF IsNil(uValue)
        ret := ""
    ELSEIF uValue:IsNumeric
        ret := uValue:ToString()  // was Ntrim(uValue)
       // ret := Ntrim(uValue)
    ELSE
        ret := uValue:ToString()
    ENDIF  
    
    RETURN IIF( ret:Length > nLength, ret:Remove( nLength ), ret:PadLeft( nLength, cFillChar[0] ) )
However, this works taking into account the decimal points:

Code: Select all

FUNCTION Start() AS VOID STRICT
    LOCAL c AS STRING
    LOCAL i AS real8
    i := 5.00
    c := PadL(i, 5, "0")    // =>  05.00
        
    Console.WriteLine(c) 
    Console.ReadKey()
RETURN 
Jamal
User avatar
Chris
Posts: 4929
Joined: Thu Oct 08, 2015 7:48 am
Location: Greece

Problem with PadL() and REAL8 parameter ?

Post by Chris »

Hi Karl,
FFF post=24335 userid=259 wrote:Chris,
why does it work with FLOAT?
That's because the FLOAT type contains formatting information, how many decimal digits should be displayed when printing the number. When using fFloat := 5, then you specify zero decimal digits to be printed when converting to string, so in this case it will give the result you would expect. But if you used fFloat := 5.000, then you would specify 3 printable decimal digits and you would get more similar results with REAL8.
Chris Pyrgas

XSharp Development Team
chris(at)xsharp.eu
User avatar
robert
Posts: 4534
Joined: Fri Aug 21, 2015 10:57 am
Location: Netherlands

Problem with PadL() and REAL8 parameter ?

Post by robert »

Karl,
FFF post=24332 userid=259 wrote:Alain,
yes. That said, i never realized, i could "pad" non strings ;-)
Seems, Real8, Real4, Double, Single are broken, while Float works as expected.
Nothing is broken.
PadL() expects a usual parameter. Usuals do not contain REAL4 (Single) or REAL8(double) values but floats.
When converting the Real4 or Real8 value to a usual then the runtime uses the current SetDecimals() setting to set the # of decimals that the usual should show when "stringifying" the value.

See https://github.com/X-Sharp/XSharpPublic ... l.prg#L121 for the usual constructor that accepts a REAL8 value.

Robert
XSharp Development Team
The Netherlands
robert@xsharp.eu
Post Reply