Mozilla Firefox extension developing. 577 < 100. How is this possible? - javascript

Here's something I haven't been able to figure out for the last 30 minutes.
var file = Components.classes["#mozilla.org/file/local;1"].
createInstance(Components.interfaces.nsILocalFile);
file.initWithPath( sPath );
...
if ( file.fileSize < (offsetContent+bytesToRead) )
{
wt.BO.log(file.fileSize + "<" + offsetContent + "+" + bytesToRead);
bytesToRead = file.fileSize - offsetContent;
}
What the above code displays is: "577 < 50 + 50"... o.O How the hell is 577 < 100? The if statement is true...can't seem to figure why.

The plus operator (+) is used to concatenate strings, or to add up numbers in JavaScript.
Since offsetContent or bytesToRead are strings, both variables are concatenated:
"50" + "50" = "5050"
When comparing these values, the string is converted to a number, and
"5050" == 5050 -> 577 < 5050 is true, of course.
Some methods to fix the code:
// Substract bytesToRead from both sides
if ( file.fileSize - bytesToRead < offsetContent )
// Or, Turn the comparison operator, and make the right side negative
if ( file.fileSize >= -bytesToRead - offsetContent )

Related

Making a thousands (k) convertor function in Javascript without rounding and NOT remove .0 from end

I am trying to make a simple 1000 to k convertor function in JS that will take a number and convert it into thousands/k. I'm having trouble getting the .toFixed(1) working properly.
I don't want it to round up and I want it to show one decimal place UNLESS that decimal is a 0. A few examples of the returns I am looking to produce are:
1100 -> 1.1K
1199 -> 1.1K
9999 -> 9.9K
10900 -> 10.9K
10999 -> 10.9K
JS
function kConvertor(num) {
return num <= 999 ? num : (num/1000).toFixed(1) + 'k'
}
This returns 10.0k which hits both cases that I do not want (9.9k).
What am I doing wrong here?
I tried adding a parseInt() and .replace('.0', '') to the end and that didn't work.
function kConvertor(num) {
return num <= 999 ? num : parseInt((num/1000)).toFixed(1).replace('.0', '') + 'k'
}
This just returns 9k
This works by using math operators to correctly round down to the nearest 10th of a K, and then uses .toFixed(1) to perform the string manipulation necessary to strip .0 from the result:
function kConverter(num) {
return num <= 999 ? num : (0.1 * Math.floor(num / 100)).toFixed(1).replace('.0','') + 'k'
}
NB: it's not good practise to have the function return a number for <= 999, or a string otherwise. Unexpected result types is the cause of the vast majority of the "WAT?!" moments from the famous video. Always ensure that your return types are consistent:
function kConverter(num) {
if (num < 1000) {
return number.toFixed(0); // assuming an integer
} else {
const s = (0.1 * Math.floor(num / 100)).toFixed(1);
return s.replace('.0', '') + 'k';
}
}

What is the reverse of the Modulo operator

I have hard time wrapping my head around how to get this to work so I came to ask the help of the brilliant minds in here.
The thing is, I want to reverse the process of the below equation so that I get X from the given Y and Z.
Z = [ ( X * 30 ) % Y ]
For the use-case, a user inputs number Y and then presses ENTER, the system get's the current server time and then multiplies that by 30. The user will then be given the remainder of the server time in format HHMMssxxx, (hmm, xxx here is the millisecond.. I don't know the format letter for millisecond.. hehe..), divided by Y - that is (X*30) % Y where X is the current server time converted to int.
How can I do this in reverse?
The catch is, X should not be greater than 2359999 -> (23:59:59.999) the maximum time value for a 24-hour clock.
Supposedly I have Z = 32, Y = 400, how can I find X?
I know that it's possible to have multiple answers. Here's what I came up so far but I think this is not very optimal in terms of performance.
function getTimeIDx(rem, codeIndexer) {
var times = [];
for(var i = 0; i < 2400000; i++) {
if((i * 30) % codeIndexer == rem) {
var str = i.toString(),
l = str.length;
if(l < 9)
str = '000000000'.substr(0, 9 - l) + str;
str = str.substr(0, 2) + ':' + str.substr(2, 2) + ':' + str.substr(4, 2) + '.' + str.substr(6);
if(/^(?:[0-1]?\d|2[0-3]):(?:[0-5]?\d):(?:[0-5]+\d)/.test(str))
times.push(str);
}
}
return times;
}
Is there some way to do this more efficiently? Is there something like a inverse modulo?
EDIT:
Updated code to check if the string is a valid time.
You cannot reverse it. Modulo is the remainder from a division operation.
Simplifying your equation. Z = Y % 2
Z is 0 for half of the values and 1 for the rest.
You can not solve for the dividend with just the remainder and the divisor.
Lets fill it into the equation:
32 = ( X * 30 ) % 400
Then this means that X * 30 is a multiple of 400 plus 32:
32
432
832
...
Now we could divide that by 30 to get x. That could be done in js like this:
function* reverse(Z, Y) {
for(let n = 0; ; n++)
yield (Z + Y * n) / 30;
}
Usable as:
for(let X of reverse(32, 400))
console.log(X);
Note that this loop will run forever as there are infinite results. Try it

Multiply & Round JavaScript issue

I'm writing a simple invoicing solution for our company and have to multiply quantity * rate and round the result to two decimal places.
Quantity: 36.5
Rate: 33.33
My multiplication looks like this:
console.log((36.5 * 33.33).toFixed(2))
which returns
1216.54
when it should actually be
1216.55
I think this is because JavaScript is rounding down instead of up. Any idea how to resolve this?
Thanks!
Function work as it described in ES standart. It doesn't round down (not always).
I skip first 7 steps of algorithm in standard (they are not significant in this case).
variables definition:
f - is number of digits required after dot
x - is number (in our case 1216.5449999)
In brackets I describe what happens and why so.
x is lower then 10^21 so
a) let n be integer for which the exact mathematical value of n ÷ 10^f – x is as close to zero as possible. (n will
be 121654)
(difference will be -0.4999999, with rights rounding (121655) difference will be (0.50000000)).
b) let m be the String consisting of the digits of the decimal representation of n (m is "121654")
c) f != 0 is true so
i) Let k be the number of characters in m.(k = 6)
ii) if k < f (not out case skipping it)
iii) Let a be the first k–f characters of m (a = "1216"), and let b be the remaining f characters of m (m = "54")
iv) Let m = a + "." + b. (m = "1216.54")
return m;
If you still worry about right rounding in your app. then you, probably, should write your own rounding method (also you may try to search npm library for it. I don't know are they exist).
Edit:
Function with right rounding (it's slow but do the trick):
function myToFixed( val, digits_num ){
if( ! digits_num ) digits_num = 0
var tmp = val.toString().split('.')
var decimal = tmp[1]
var full = tmp[0];
var regex = /[5-9]/
var match = regex.exec( decimal.slice( digits_num ) )
if( ! match ){ return val.toFixed( digits_num ) }
var i = match.index + digits_num
while( i >= digits_num ){ val = ( parseFloat( val ).toFixed( i ) ); i-- }
return val.toString()
}

counter with multiple digits

I'm fairly new to Javascript and have been able to get by so far by just following tutorials and reading forums but this one really stumped me for a while.
Basically I wanted to have a counter for numbers that contain seven digits, I found a few things but none that really made sense to me so I wrote this:
imgNumber++;
if (imgNumber < 10){function add(number){return '00000' + number}};
if (imgNumber > 10 && imgNumber < 100){function add(number){return '0000' + number}};
if (imgNumber > 100 && imgNumber < 1000){function add(number){return '000' + number}};
if (imgNumber > 1000 && imgNumber < 10000){function add(number){return '00' + number}};
if (imgNumber > 10000 && imgNumber < 100000){function add(number){return '0' + number}};
if (imgNumber > 100000 && imgNumber < 1000000){function add(number){return '' + number}};
It works as far as I can tell. My question is this: Do you foresee any issues with this and if not is there a cleaner way to write all this?
I'll appreciate any and all replys.
Cheers,
Colin
As with all programming functions are your friend. I searched google for padding zeros javascript and got directed to this site.
function pad(number, length) {
var negative = number < 0;
var str = '' + Math.abs(number);
while (str.length < length) {
str = '0' + str;
}
if(negative) str = '-' + str;
return str;
}
Using this you would just generate your number standard and prior to storing/outputting it you'd run it through this function:
pad(1,7);
A one liner:
var output = sprintf("%07d", 30);
Believe me, it will save you a lot of time in javascript (and in other languages). You can download the implementation in http://sprintf.googlecode.com/files/sprintf-0.7-beta1.js
By today, this code works right now, perhaps you need to change the src of the library for a more updated:
<script type="text/javascript" src="http://sprintf.googlecode.com/files/sprintf-0.7-beta1.js"> </script>
<script type="text/javascript" >
alert(sprintf("%04d",4));
</script>
More information, here, plus there are other implementations of this useful method.
Why don't you just take the log (base 10) of the number as an indicator of how many digits to add.
If log(N) is between 0 and less than 1, N is a one digit number.
If log(N) is greater than or equal to 1 but less than 2, N has two digits, and so forth.
I don't actually code in JavaScript, so I don't know if you have access to a log function, but if you do, this is a very terse way to get the result.
John Doner

Modulo in JavaScript - large number

I try to calculate with JS' modulo function, but don't get the right result (which should be 1). Here is a hardcoded piece of code.
var checkSum = 210501700012345678131468;
alert(checkSum % 97);
Result: 66
Whats the problem here?
Regards,
Benedikt
For an IBAN calculation form a normal bankaccount number I end up with a very large number contained in a string datatype. From this large number I have to find the rest when divided by 97 -> large number % 97.
As soon as I convert the datatype to an integer I get an overflow resulting in a negative integer and eventually a wrong rest value. As I saw some verbose pieces of code (which also gave wrong outcome), I could not resist to share my own. Credits go to Finding Modulus of a Very Large Number with a Normal Number
modulo: function(divident, divisor) {
var partLength = 10;
while (divident.length > partLength) {
var part = divident.substring(0, partLength);
divident = (part % divisor) + divident.substring(partLength);
}
return divident % divisor;
}
N.B.
I use 10 positions here as this is smaller than the 15 (and some) positions of max integer in JavaScript, it results in a number bigger than 97 and it's a nice round number. The first two arguments matter.
A bunch of improvements to Benedikt's version: "cRest += '' + cDivident;" is a bugfix; parseInt(divisor) makes it possible to pass both arguments as strings; check for empty string at the end makes it always return numerical values; added var statements so it's not using global variables; converted foreach to old-style for so it works in browsers with older Javascript; fixed the cRest == 0; bug (thanks #Dan.StackOverflow).
function modulo (divident, divisor) {
var cDivident = '';
var cRest = '';
for (var i in divident ) {
var cChar = divident[i];
var cOperator = cRest + '' + cDivident + '' + cChar;
if ( cOperator < parseInt(divisor) ) {
cDivident += '' + cChar;
} else {
cRest = cOperator % divisor;
if ( cRest == 0 ) {
cRest = '';
}
cDivident = '';
}
}
cRest += '' + cDivident;
if (cRest == '') {
cRest = 0;
}
return cRest;
}
For those who simply want to copy&paste a working (functional) solution in ES6 to check IBANs:
function isIBAN(s){
const rearranged = s.substring(4,s.length) + s.substring(0,4);
const numeric = Array.from(rearranged).map(c =>(isNaN(parseInt(c)) ? (c.charCodeAt(0)-55).toString() : c)).join('');
const remainder = Array.from(numeric).map(c => parseInt(c)).reduce((remainder, value) => (remainder * 10 + value) % 97,0);
return remainder === 1;}
You could even write it as a one-liner.
The modulo operation is performed on the array of integers storing the actual number (divident, applied as string to function):
function modulo(divident, divisor){
return Array.from(divident).map(c => parseInt(c)).reduce((remainder, value) => (remainder * 10 + value) % divisor,0);
};
This works because Modulo is distributive over addition, substraction and multiplication:
(a+b)%m = ((a%m)+(b%m))%m
(a-b)%m = ((a%m)-(b%m))%m
(ab)%m = ((a%m)(b%m))%m
The IBAN function transpiled to ES5 looks like:
function (s) {
var rearranged = s.substring(4, s.length) + s.substring(0, 4);
var numeric = Array.from(rearranged).map(function (c) { return (isNaN(parseInt(c)) ? (c.charCodeAt(0) - 55).toString() : c); }).join('');
var remainder = Array.from(numeric).map(function (c) { return parseInt(c); }).reduce(function (remainder, value) { return (remainder * 10 + value) % 97; }, 0);
return remainder === 1;
};
looks like you've fallen victim to this: What is JavaScript's highest integer value that a Number can go to without losing precision?
just to reiterate what's in the other thread:
they are 64-bit floating point values, the largest exact integral value is 2^53. however, from the spec section [8.5: Number Type]:
Some ECMAScript operators deal only with integers in the range −2^31 through 2^31−1, inclusive, or in the range 0 through 2^32−1, inclusive. These operators accept any value of the Number type but first convert each such value to one of 2^32 integer values. See the descriptions of the ToInt32 and ToUint32 operators in sections 0 and 0, respectively
But credit where credit is due. Jimmy got the accepted answer over there for doing the legwork (well, googling).
Finally, my solution:
function modulo (divident, divisor) {
cDivident = '';
cRest = '';
for each ( var cChar in divident ) {
cOperator = cRest + '' + cDivident + '' + cChar;
if ( cOperator < divisor ) {
cDivident += '' + cChar;
} else {
cRest = cOperator % divisor;
if ( cRest == 0 ) cRest = '';
cDivident = '';
}
}
return cRest;
}
Silent Matt has developed a Javascript library for Big Integers. It could solve this issue too.

Categories

Resources