Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Weird issue in Ubuntu QML apps #15

Closed
josdejong opened this issue Apr 26, 2015 · 12 comments
Closed

Weird issue in Ubuntu QML apps #15

josdejong opened this issue Apr 26, 2015 · 12 comments

Comments

@josdejong
Copy link

A user of math.js reported some weird behavior when using big numbers (powered by decimal.js). When using decimal.js in an Ubuntu HTML5 app (QML), for some inputs there are digits lost. Here is some example output:

console.log(new Decimal('3.33300000003').toString());  // 3.00000000003   WRONG
console.log(new Decimal('33.3300000003').toString());  // 33.0000000003   WRONG
console.log(new Decimal('33.33000003').toString());    // 33.00000003     WRONG
console.log(new Decimal('33.330003').toString());      // 33.330003       OK

I'm not familiar with QML myself, but installed the SDK and verified this behavior. I'm not sure what JavaScript engine is used but I thought it was Chromium. When loading decimal.js into the QML app, I got a warning that decimal.js could not be loaded as UTF8, but I don't think that is related. I also verified that the problem is in constructing a Decimal, it's not in the toString method (I just looked at the digits in the .c array).

Do you have any clue what could cause this issue?

@MikeMcl
Copy link
Owner

MikeMcl commented Apr 26, 2015

No, but I will look into it.
I'll install the 700 MB (!) Qt download tomorrow.
Do you any advice on how I can quickly set it up to test this?

@josdejong
Copy link
Author

Thanks!

What I did was

  • Install the Ubuntu SDK: https://developer.ubuntu.com/en/start/ubuntu-sdk/installing-the-sdk/

  • I had to install a few missing libraries as well (running Linux Mint here), just read the errors if any.

  • Start the Ubuntu SDK, create a new project (Ubuntu, QML App with simple UI (qmlproject)). I used a "Desktop" for Kit selection.

  • Add decimal.js to the project. Select some proper encoding for it (The editor can't load it as UTF-8)

  • Inside decimal.js, comment the UMD exports part, and instead create a global variable var Decimal containing the exported prototype.

  • Replace the contents of Main.qml with the following (basically adding an import and replacing the onClicked function:

    import QtQuick 2.0
    import Ubuntu.Components 1.1
    
    import 'decimal.js' as DecimalExports
    
    /*!
        \brief MainView with a Label and Button elements.
    */
    
    MainView {
        // objectName for functional testing purposes (autopilot-qt5)
        objectName: "mainView"
    
        // Note! applicationName needs to match the "name" field of the click manifest
        applicationName: "test7.username"
    
        /*
         This property enables the application to change orientation
         when the device is rotated. The default is false.
        */
        //automaticOrientation: true
    
        // Removes the old toolbar and enables new features of the new header.
        useDeprecatedToolbar: false
    
        width: units.gu(100)
        height: units.gu(75)
    
        Page {
            title: i18n.tr("Simple")
    
            Column {
                spacing: units.gu(1)
                anchors {
                    margins: units.gu(2)
                    fill: parent
                }
    
                Label {
                    id: label
                    objectName: "label"
    
                    text: i18n.tr("Hello..")
                }
    
                Button {
                    objectName: "button"
                    width: parent.width
    
                    text: i18n.tr("Tap me!")
    
                    onClicked: {                    
                        var Decimal = DecimalExports.Decimal;
                        console.log(new Decimal('3.33300000003').toString());  // 3.00000000003   WRONG
                        console.log(new Decimal('33.3300000003').toString());  // 33.0000000003   WRONG
                        console.log(new Decimal('33.33000003').toString());    // 33.00000003     WRONG
                        console.log(new Decimal('33.330003').toString());      // 33.330003       OK
    
                    }
                }
            }
        }
    }
    
  • Now, run the project and click the button in the app, then you will see the following output in the console:

    3.00000000003
    33.0000000003
    33.00000003
    33.330003
    

@bartoszkosiorek
Copy link

The easiest way to reproduce this bug on Ubuntu:

  1. Download Ubuntu 15.04 and create bootable USB
  2. Run Ubuntu from USB
  3. Install SDK: Open terminal and type "sudo apt-get install ubuntu-sdk"
  4. Create "Main.qml" file with code provided by Jos (see above)
  5. Place decimal.js in the same directory as "Main.qml"
  6. Inside decimal.js, comment the UMD exports part, and instead create a global variable var Decimal containing the exported prototype.
  7. In terminal type "qmlscene Main.qml"

@MikeMcl
Copy link
Owner

MikeMcl commented Apr 28, 2015

@Gang65

Thanks. I'll have a look later this week.

@josdejong
Copy link
Author

I found the cause of this issue, it's in the Decimal constructor: https://github.com/MikeMcl/decimal.js/blob/master/decimal.js#L3598-L3600

// This goes wrong in the QML app
for ( b -= LOGBASE; i < b; ) {
    x['c'].push( +n.slice( i, i += LOGBASE ) );
}

// This works fine in the QML app
for ( b -= LOGBASE; i < b; ) {
    var next = i + LOGBASE;
    x['c'].push( +n.slice( i, next ) );
    i = next;
}

So it looks like the the JS engine of QML builds up the arguments for the slice function call after evaluating i += LOGBASE, passing the wrong (already updated value) of i to the function. Sounds like a bug in the JS engine and we should report that. But besides that it would be great if you could workaround this issue in decimal.js (it's just a simple fix).

@josdejong
Copy link
Author

So to sumarize the issue:

var i = 2;
console.log(i, i += 2);
// output in Chrome, Firefox: 2, 4
// output in QML app:         4, 4 (WRONG?)       

@Gang65 do you know where we should report this issue?

@josdejong
Copy link
Author

I've created a bug report here: https://bugreports.qt.io/browse/QTCREATORBUG-14367

@bartoszkosiorek
Copy link

There is some nice discussion on Google+, about that issue:
https://plus.google.com/+RiccardoPadovani/posts/FAyiPz3TqCo

According to that discussion, it is not a bug in ECMAscript engine.
@MikeMcl Do you think it will be possible to update decimal.js/bignumber.js script to be universal and not dependent on order of execution for function arguments?

@josdejong
Copy link
Author

Ah, so this behavior is not standardized. That's interesting...

@MikeMcl
Copy link
Owner

MikeMcl commented Apr 29, 2015

That discussion is interesting - thanks for the link - but I don't want to start making changes based upon that alone.

And one of the later posts links to stackoverflow, which gives a more convincing assertion that the order of evaluation of function arguments is left to right - as is true of every other JS engine I have come across.

I think it will be accepted as a bug, and fixed in due course.

Anyway, I will do some research myself...

@josdejong
Copy link
Author

Good find @MikeMcl , so it turns out it is defined in the specs...

@MikeMcl
Copy link
Owner

MikeMcl commented May 1, 2015

Its amusing to see the code proposals that have been added at that Google+ link, but I think I'll be leaving it as it is for now. I will be reviewing/tidying up the code at some point soon anyway - among other things, I want to get rid of the square bracket notation for object properties.

I also added an answer on stackoverflow which clearly shows that the left to right evaluation order has been in JavaScript from the beginning.

@MikeMcl MikeMcl closed this as completed Jun 12, 2015
Flohack74 pushed a commit to ubports/calculator-app that referenced this issue May 8, 2017
Flohack74 pushed a commit to ubports/calculator-app that referenced this issue May 8, 2017
MikeMcl/decimal.js#15. Fixes: https://bugs.launchpad.net/bugs/1450172.

Approved by Ubuntu Phone Apps Jenkins Bot, Riccardo Padovani.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants