NIP with unexpected 6dp value

Andrew Cheung
Andrew Cheung Newcomer

We have a NIP publish live updates to TREP, any idea what is the problem?

When we do publish from RFA C++ via NIP with 2dp and it publish unexpected 6dp value

small program create a publisher, Publishes UPLIMIT=0, then UPLIMIT=2109.45 and finally UPLIMIT=2109.45 with precision hint as 2. All these values directly hard coded in the code. why we got unexpected 6dp

UPLIMIT : REAL 2 : [0.000000]

UPLIMIT : REAL 5 : [2109.449999]

UPLIMIT : REAL 4 : [2109.44]

Tagged:

Best Answer

  • Jirapongse
    Jirapongse ✭✭✭✭✭
    Answer ✓

    @Andrew Cheung @Kung.S

    I think it could be a limitation when multiplying double and integer, as mentioned in this thread.

    For example, the following code prints 2109449999, not 2109450000.

        Int64  x = 2109.45 * 1000000;
        printf("#### %lld \n", x); //2109449999

    You can try the solution (llround) mentioned in that thread.

        Int64  x = llround(2109.45 * 1000000);
        printf("#### %lld \n", x); //2109450000


Answers

  • Hi @Andrew Cheung

    Please share the code snippet you use to encode the above fields.

    Also, enable IPCTrace in RFA and share the trace file - so we can see what is happening at the wire level - as described in Activate full message logs for RSSL connections in RFA C++ - Forum | Refinitiv Developer Community

    The example above is for a standard Consumer RSSL connection - you will need to apply similar changes for the RSSL_NIPROV connection being used by your NIP.

    Also, if you are writing a new NIP from scratch or upgrading an existing NIP application, I strongly recommend you use Enterprise Message API - which is part of our strategic RT-SDK - and is much easier to learn and code in than RFA.

    RFA is a feature-complete/legacy API with no new features etc to be supported in the future - other than basic maintenance releases.

  • Kung.S
    Kung.S Newcomer

    It appears that some of the value will be correct, and some will be wrong when we set the precisionHint to various values.


    For instance

    Double value 2109.45

    precision 6

    <FS>316<US>XX<GS>ASOK.BO<US><RS>

    UPLIMIT : REAL 11 : [2109.449999]

    precision 7

    <FS>316<US>XX<GS>ASOK.BO<US><RS>

    UPLIMIT : REAL 12 : [2109.4500000]

    precision 8

    <FS>316<US>XX<GS>ASOK.BO<US><RS>

    UPLIMIT : REAL 13 : [2109.44999999]

    precision 9

    <FS>316<US>XX<GS>ASOK.BO<US><RS>

    UPLIMIT : REAL 14 : [2109.449999999]

    Double value 103.07

    precision 6

    <FS>316<US>XX<GS>ASOK.BO<US><RS>

    UPLIMIT : REAL 10 : [103.070000]

    precision 7

    UPLIMIT : REAL 11 : [103.0699999]

    precision 8

    <FS>316<US>XX<GS>ASOK.BO<US><RS>

    UPLIMIT : REAL 12 : [103.07000000]

    precision 9

    <FS>316<US>XX<GS>ASOK.BO<US><RS>

    UPLIMIT : REAL 13 : [103.070000000]


    Here is the code which calls RFA to publish the data

    void RFAPubMessage::setDoubleValue(double dValue, IMDFieldDescriptor* fDesc, unsigned int precisionHint)

    {

    m_dataBuffer.clear();

    RFAFieldDescriptor* rfaDesc = reinterpret_cast<RFAFieldDescriptor*>(fDesc);

    switch (rfaDesc->fDef()->getOMMType())

    {

    case rfa::data::DataBuffer::Real32Enum:

    case rfa::data::DataBuffer::Real64Enum:

    {

    rfa::data::Real64 realValue;

    if ((rfa::common::UInt8)precisionHint > rfa::data::Exponent0){

    precisionHint = (unsigned int)rfa::data::Exponent0;

    }

    realValue.setValue((rfa::common::Int64)(dValue * s_nDecimalMap[precisionHint]));

    realValue.setMagnitudeType(rfa::data::Exponent0 - (rfa::common::UInt8)precisionHint);

    m_dataBuffer.setReal(realValue);

    break;

    }

    case rfa::data::DataBuffer::DoubleEnum:

    m_dataBuffer.setDouble(dValue);

    break;

    case rfa::data::DataBuffer::FloatEnum:

    m_dataBuffer.setFloat((rfa::common::Float)dValue);

    break;

    default:

    throw MDETException (MD_INVALID_DATA_TYPE, "Data type mismatch!");

    }

    m_fieldEntry.clear();

    m_fieldEntry.setFieldID((rfa::common::Int16)fDesc->getFieldId());

    m_fieldEntry.setData(m_dataBuffer);

    m_fieldListIterator.bind(m_fieldEntry);

    }