You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@daffodil.apache.org by "Steve Lawrence (JIRA)" <ji...@apache.org> on 2019/01/03 13:32:00 UTC

[jira] [Comment Edited] (DAFFODIL-2043) fn:round-half-to-even returns decimal string

    [ https://issues.apache.org/jira/browse/DAFFODIL-2043?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16733018#comment-16733018 ] 

Steve Lawrence edited comment on DAFFODIL-2043 at 1/3/19 1:31 PM:
------------------------------------------------------------------

The difference here is subtle, and certainly a bug in Daffodil. The first two expression (which compile to the same thing), compile to the following XML representation:
{code:xml}
<CompiledDPath>
	<FNRoundHalfToEven1>
		<CompiledDPath>
			<Literal>0.1</Literal>
		</CompiledDPath>
	</FNRoundHalfToEven1>
	<NumericToString/>
	<StringToLong/>
	<LongToInt/>
</CompiledDPath>
{code}

Note that the result of fn:round-half-to-even is a numeric, so that numeric must be converted to an int. This is done by converting the numeric to a string, then converting the string to a long (implemented via the String.toLong method), which is finally converted to an Int. However, the fn:round-half-to-even method can return a decimal, in which case the String.toLong method will fail.

If we look at the working expression, it's compiled XML representation is the following:
{code:xml}
<CompiledDPath>
	<FNRoundHalfToEven1>
		<CompiledDPath>
			<Literal>0.1</Literal>
		</CompiledDPath>
	</FNRoundHalfToEven1>
	<NumericToString/>
	<StringToDouble/>
	<DoubleToLong/>
	<LongToInt/>
</CompiledDPath>
{code}

So the xs:double cast results in a StringToDouble which is implemented as String.toDouble. This will correctly convert the string to a Double. That Double is then converted to a Long via Double.toLong which works as one might expect by just dropping precision.

I suspect casting a Numeric to a String and then casting the String to the target type is probably not the way right way to handle casting Numerics.


was (Author: slawrence):
The difference here is subtle, and certainly a bug in Daffodil. The first two expression (which compile to the same thing), compile to the following XML representation:
{code:xml}
<CompiledDPath>
	<FNRoundHalfToEven1>
		<CompiledDPath>
			<Literal>0.1</Literal>
		</CompiledDPath>
	</FNRoundHalfToEven1>
	<NumericToString/>
	<StringToLong/>
	<LongToInt/>
</CompiledDPath>
{code}

Note that the result of fn:round-half-to-even is a numeric, so that numeric must be converted to an int. This is done by converting the numeric to a string, then converting the string to a long (implemented via the String.toLong method), which is finally converted to an Int. However, the fn:round-half-to-even method can return a decimal, in which case the String.toLong method will fail.

If we look at the working expression, it's compiled XML representation is the following:
{code:xml}
{code}

> fn:round-half-to-even returns decimal string
> --------------------------------------------
>
>                 Key: DAFFODIL-2043
>                 URL: https://issues.apache.org/jira/browse/DAFFODIL-2043
>             Project: Daffodil
>          Issue Type: Bug
>            Reporter: Brandon Sloane
>            Priority: Major
>         Attachments: test.dfdl.xsd
>
>
> fn:round-half-to-even() appears to be returning a decimal string, which causes issues when an integer type is expected.
> The following elements both trigger a schema definition error
> <xs:element name="a" type="xs:int"
>  dfdl:inputValueCalc="\{ (fn:round-half-to-even( 0.1 )) }"
>  />
> <xs:element name="a" type="xs:int"
>  dfdl:inputValueCalc="\{ xs:int(fn:round-half-to-even( 0.1 )) }"
>  />
> [error] Schema Definition Error: Cannot convert '0.0' from String type to Long (Cannot convert to type long: For input string: "0.0").
> In contrast, casting to a double, as below, appears to work as expected:
> <xs:element name="a" type="xs:int"
>  dfdl:inputValueCalc="\{ xs:double(fn:round-half-to-even( 0.1 )) }"
>  />
>  
> What appears to be happening is that fn:round-half-to-even( 0.1 ) returns the string "0.0", and the type="xs:int" on the element triggers an implicit cast to an integer type. Since "0.0" contains a decimal point, this cast fail. However, an explict cast to xs:double can succeed, and then the explicit cast to an int from the double works as expected.
> Complete example schema attached



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)