# Bignums works differently on different computers

Hi all, I've got another problem with bignums.

The project below, everybody in my class was able to follow along and build the same thing and it worked, except for one student. He's checked the javascript extensions, he's clicked on the bignums, but still it doesn't work. Because the big number is prime (it's one of the two published prime factors of RSA-100), the correct result is 1, but he gets some other random large number. I even exported my working project as xml, sent it to him, he loaded it up and it did the same.

Also his project behaves correctly with smaller numbers that don't need Bignums.

When class time ran out, I suggested he try other browsers/computers. But what else might cause Bignums (or javascript generally) to behave differently for some users than others?

EDIT: I found a more repeatable problem and have updated the post.

Click the eyeball to open the project, go in the gear menu and enable javascript extensions, then run the script. FIRST run it says false (which is incorrect), and also says the base that it used. SECOND and all subsequent runs works.

Is there some amount of time it takes for enabled javascript extensions, or clicking on USE BIGNUMS to work?

Just to clarify: You're saying he gets a different number each time?

The project you posted looks like not his actual project but rather something you made just to post here. Can we see his original project?

And, what can you tell us about his computer's OS, browser, and versions?

Unless his computer is extremely exotic I'm having trouble imagining how this can be true...

No, not a different number each time, he gets a repeatable wrong number.

His actual project I don't have but it's irrelevant, he got the same problem loading up an exported xml of this project (minus the comments and the Say block)

He had a hp laptop with windows, probably windows 10. I don't know the browser/version but if he gets back to me about trying different browsers/computers I'll ask.

Oh yeah, his screen is cracked, I told him he should get it fixed, maybe the bignums would work

Actually I do have his project, he sent me a shared link, but I don't have permission to post it for the world. I tested it, and in my browser it works.

You may look at a debug console (F12), to check if "//snap.berkeley.edu/snap/libraries/biginteger.js" is not blocked by browser/firewall on this computer.

I don't know if I'm missing a joke, but I'm pretty sure a broken screen doesn't have anything to do with the actual functioning of the system...

Yes I was joking. But it did get broken because he stepped on the whole laptop, who knows what could have happened to the motherboard/cpu etc. But hard to imagine this little thing is the only consequence!

Thanks, that's a good idea (the F12 log thing)

It's weird (here's another clue), I put a say block in there to show the successive BIGNUMs it was halving and halving (with floor), and it showed bignums for a little bit, and then it switched to scientific notation (indicating to me it had somehow switched into floating point).

I tried to force it by having him wrap the floor with a round (this was a workaround for one of my earlier bignum problems), and that did get him all bignums all the time, but not the right answer.

The cacluation is 5^(p-1)mod p, where p is a 50-digit prime, and any arithmetic error (like a human would do) would result in a random number less than p, so probably a 50-digit random (repeatable) number, which is what his results look like.

I'm looking at floor and round, and the only difference in our part of the code is that round has the line

          if (fn["integer?"](x)) return fn["exact"](x);


where x is the value returned by Scheme round. We locally hack INTEGER? to

integer?(x) || integer-valued?(x)


but as I read the code this is relevant only if x is of type COMPLEX (and its imaginary part is zero).

So this turns an integer value (which should include an integer-valued IEEE float) into a JS integer or into a bignum.

So, backing out a level of detail, we modify the Scheme ROUND so that its result is not merely a mathematical integer but also a CS integer.

So, finally to the endpoint of all this, the reason your ROUND workaround worked for you is that it makes its result Scheme-exact, and instead of calling ROUND you can do the same thing explicitly with

Please try that experiment on his computer.

This doesn't tell us why his computer does floating point conversion differently from anyone else's, but I'm tempted to say that if we can work around it we don't have to know. :~)

I know, right?

I will try that, won't be til Wed.

Separate question/idea, it would be nice if there were an integer-only division, like if you could relabel (/) as (//) (borrowing python syntax), rather than using floor(n/2).

I guess also I could try (n-1)/2. Does Snap keep numbers integer when possible? (Or is that a question for javascript or bignums or scheme)?

#ROTFLOL at that picture/caption

When bignums aren't enabled, Snap! uses native JS numbers, i.e., always in long float format.

When bignums are enabled, yes, we try to keep integers as integers, e.g., we check specifically for taking the square root of a square integer. The line of code I quoted above, in ROUND, is another example. Certainly division of two integers will never yield a float; at worst it'll give an exact rational.

PS I learned "If it works, leave it alone" as the First Law of Engineering, not just programming. Another variant is "if it's not broken, don't fix it." Of course this law is often honored in the breach, as when optimizing code.

"if it ain't broke" depends (or should) on context. If you're dealing with a legacy system that was constructed with poor architectural principles and is fragile so that an apparent 'fix' will break things elsewhere (because other pieces of code were depending on the part you're looking on being broken in exactly the way it is (sometimes knowingly!)), then yeah, be very careful.

But if you're writing something small, everything is new and subject to change anyways, probably better to learn the instinct to 'measure twice cut once', or buy yourself easy down the road, by paying some extra effort now. Also if the whole time the system was built that way it should not be fragile, and should withstand 'if it's broke, fix it'

Yeah that's good engineering.

Alas, I learned to program at the MIT AI lab, where the development process was to write something overnight, then install it for users, then go to sleep in the lab, with the expectation that if anyone finds a bug they'll wake you up. :~) They shouldn't let me teach children, really...

I found a more repeatable behavior, I wonder if this is what I was seeing on my student's computer.

Two other students submitted their homework, first run it didn't work right, then subsequent runs it did work right.

I've edited the sample script for this post and I'm seeing the same behavior. If you click green flag it says you need javascript extensions, so click the eyeball to open, then enable javascript extensions, and then run the script, it should say a number, and then say false -- that is the error in action. After that first error, you can run it again and again and it works correctly (does 100 tests and reports True)

Do others see that behavior? I'm not sure what would be a more succinct/concrete way to demonstrate the bug

It's like the time from executing USE BIGNUMS to actually using bignums is maybe not long enough to make the effects of USE BIGNUMS fully propagate or something? (or enabling javascript extensions?)

Although this doesn't explain why the student from the original post, I saw this happening over and over, maybe on his computer bignums was taking minutes to spin up, instead of a second?

OK here it is in shortest form:

Inserting a [wait 1 sec] before the [script variables a] fixes that problem, seems like USE BUGNUMS isn't really done doing what it does when it hands off to the next block in its script

Yes, I confirm this fails for me in the same way in the 6.9 library. But it's fixed in 7.0, so I hereby declare it not worth worrying about. :~)