i got a strange error message

Discussion in 'Javascript' started by greenflame, Jun 20, 2005.

  1. greenflame

    greenflame Guest

    I have the following function. It is supposed to multiply all the
    elements of a matrix by a specified factor. It tells me that on "line
    58" that undefined is null or not an object. Here is the code:

    function scalematrix(input,factor) {
    if (input[0].length == undefined) {
    var output = copy1darr(input);
    for (var i=0;i<output.length;i++) {
    output *= factor;
    }
    return output;
    } else {
    var output = copy2darr(input);
    for (var i=0;output.length;i++) {
    for (var j=0;j<output[0].length;j++) {
    output[j] *= factor; // This is "line 58"
    }
    }
    return output;
    }
    }

    I tried to figure out what was wrong but I could not. Can anyone help
    me, please? Well, I have lots of other functions but if I include them,
    the code will be real long.
    greenflame, Jun 20, 2005
    #1
    1. Advertising

  2. greenflame

    Ivo Guest

    "greenflame" sais
    > I have the following function. It is supposed to multiply all the
    > elements of a matrix by a specified factor. It tells me that on "line
    > 58" that undefined is null or not an object. Here is the code:
    >

    <snip>
    > var output = copy2darr(input);
    > for (var i=0;output.length;i++) {
    > for (var j=0;j<output[0].length;j++) {
    > output[j] *= factor; // This is "line 58"
    > }
    > }

    <more snip>

    Check for the existence of copy2darr with alert(copy2darr); or check its
    return value, alert( output && output[j] ), is it really the
    multi-dimensional array that this code blindly expects?

    Oh, forget that. Now I see that the condition in your outer loop contains
    what is probably a typo. You get the error message when i gets greater
    output.length. You wrote:

    > for (var i=0;output.length;i++) {


    Of course you meant:
    for (var i=0;i<output.length;i++) {

    hth
    Ivo
    http://www.nostradamus.onlyfools.com/
    Ivo, Jun 20, 2005
    #2
    1. Advertising

  3. greenflame

    RobG Guest

    greenflame wrote:
    > I have the following function. It is supposed to multiply all the
    > elements of a matrix by a specified factor. It tells me that on "line
    > 58" that undefined is null or not an object. Here is the code:
    >
    > function scalematrix(input,factor) {
    > if (input[0].length == undefined) {


    The first element of the array may be a string, e.g. '5' and will have
    a length. Your test will assume it is an array. A better (though not
    thorough) test would be:

    if ( input[0] && !isNaN(input[0]) ) {

    > var output = copy1darr(input);


    The copy function is not required, just create a new, empty array:

    var output = [];

    > for (var i=0;i<output.length;i++) {
    > output *= factor;


    And put the new values into it:

    output = input*factor;

    > }
    > return output;
    > } else {
    > var output = copy2darr(input);


    Same as above, just create a new, empty array:

    var output = [];


    > for (var i=0;output.length;i++) {


    This is not a comparison ---^^ , try this:

    for (var i=0; i<output.length; i++) {


    > for (var j=0;j<output[0].length;j++) {
    > output[j] *= factor; // This is "line 58"


    output[j] = input[j]*factor;

    > }
    > }
    > return output;
    > }
    > }
    >
    > I tried to figure out what was wrong but I could not. Can anyone help
    > me, please? Well, I have lots of other functions but if I include them,
    > the code will be real long.
    >


    Here's the full, fixed script:

    function scalematrix(input,factor) {

    if ( input[0] && !isNaN(input[0]) ) {
    var output = [];
    for (var i=0; i<input.length; i++) {
    output = input*factor;
    }
    return output;
    } else {
    var output = [];
    for (var i=0; i<input.length; i++) {
    output = [];
    for (var j=0; j<input.length; j++) {
    output[j] = input[j]*factor;
    }
    }
    return output;
    }
    }

    var A = [ [1, 2], [3, 4]];
    var B = scalematrix(A, 5);
    alert(
    'A:\n' + A.join('\n') + '\n\n' +
    'B:\n' + B.join('\n')
    );


    Below is a general function for multiplying a matrix of any dimension -
    1d, 2d, 3d, etc. It may be a little slow for bigger multi-dimensional
    arrays, but for smaller ones it should be fine.

    It only does cursory checking to see if A is an object, if not, it
    tries to multiply it by 'n'. If A is actually a string that can't be
    converted to a number (e.g. 'george'), 'NaN' will be returned. If A is
    a function, it will bomb (so you can't just throw anything at it).

    // Multiply an n dimension array
    function multiplyArr( A, n ) {
    if ( 'object' != typeof A ) { return A*n; }
    var i = A.length;
    var B = []
    while ( i-- ) {
    B = multiplyArr( A, n );
    }
    return B;
    }

    var D = [
    [ 1, 2,],
    [
    [ 3, 4],
    [ 5, 6]
    ],
    [7, 8]
    ];

    var C = multiplyArr( D, 6);
    alert( 'C: \n' + C.join('\n') );




    --
    Rob
    RobG, Jun 20, 2005
    #3
  4. On 20/06/2005 01:33, RobG wrote:

    > greenflame wrote:


    [snip]

    >> if (input[0].length == undefined) {

    >
    > The first element of the array may be a string, [...] A better (though not
    > thorough) test would be:
    >
    > if ( input[0] && !isNaN(input[0]) ) {


    A thorough test for an array (or rather, not an array) would be:

    if(input[0] && (Array != input[0].constructor)) {

    [snip]

    > if ( input[0] && !isNaN(input[0]) ) {
    > var output = [];
    > for (var i=0; i<input.length; i++) {
    > output = input*factor;
    > }
    > return output;


    To remove a bit of redundancy, you could move the output declaration and
    initialisation to the top of the function, and the return statement to
    the end.

    [snip]

    Mike

    --
    Michael Winter
    Replace ".invalid" with ".uk" to reply by e-mail.
    Michael Winter, Jun 20, 2005
    #4
  5. greenflame

    RobG Guest

    Michael Winter wrote:
    > On 20/06/2005 01:33, RobG wrote:
    >
    >> greenflame wrote:

    >
    >
    > [snip]
    >
    >>> if (input[0].length == undefined) {

    >>
    >>
    >> The first element of the array may be a string, [...] A better
    >> (though not
    >> thorough) test would be:
    >>
    >> if ( input[0] && !isNaN(input[0]) ) {

    >
    >
    > A thorough test for an array (or rather, not an array) would be:
    >
    > if(input[0] && (Array != input[0].constructor)) {


    Yes, but it still assumes tht input[0] (if it exists) is either an
    array or a number (or a string that will convert to a number).

    Is this 'better' or just another way of choosing which branch of the if
    to execute?

    >
    > [snip]
    >
    >> if ( input[0] && !isNaN(input[0]) ) {
    >> var output = [];
    >> for (var i=0; i<input.length; i++) {
    >> output = input*factor;
    >> }
    >> return output;

    >
    >
    > To remove a bit of redundancy, you could move the output declaration and
    > initialisation to the top of the function, and the return statement to
    > the end.


    Yes, good idea. For Greenflame's benefit:


    function scalematrix(input,factor) {
    var output = [];
    if( input[0] && (Array != input[0].constructor) ) {
    for (var i=0; i<input.length; i++) {
    output = input*factor;
    }
    } else {
    for (var i=0; i<input.length; i++) {
    output = [];
    for (var j=0; j<input.length; j++) {
    output[j] = input[j]*factor;
    }
    }
    }
    return output;
    }


    --
    Rob
    RobG, Jun 20, 2005
    #5
  6. On 20/06/2005 03:19, RobG wrote:

    > Michael Winter wrote:


    [snip]

    >> A thorough test for an array (or rather, not an array) would be:
    >>
    >> if(input[0] && (Array != input[0].constructor)) {

    >
    > Yes, but it still assumes tht input[0] (if it exists) is either an
    > array or a number (or a string that will convert to a number).


    If input is a 'matrix', then what else would the elements be? As I see
    it, the second branch is to be executed when input is an array of
    arrays. The first branch is to be executed otherwise. That is, if input
    is an array of numbers, or possibly values or objects that can be
    converted to numbers.

    If some other case occurs, then that would be a error in the client
    code, and the OP should decide whether this function should be capable
    of detecting and dealing with such problems, or just mandating that a
    caller gets things right.

    > Is this 'better' or just another way of choosing which branch of the
    > if to execute?


    Both, probably. However, it would only be 'better' in that it checks for
    the determining factor: whether the element is an array, or not.

    [snip]

    Mike

    --
    Michael Winter
    Replace ".invalid" with ".uk" to reply by e-mail.
    Michael Winter, Jun 20, 2005
    #6
  7. greenflame

    greenflame Guest

    Everyone: So it is more efficient to fill in an empty array then to
    copy one and shange the values? Also, since the idea has been brought
    up, Is there a way good way to make an iff block that checks whether a
    variable is a string, number, "1D Matrix", "2D Matrix, ... etc. A "1D
    Matrix is just an array. A "2D Matrix" is an arry of arrays.

    Rob G: Does your multuplyArr function just multiply all the elements of
    an "n dimensional matrix" by a certain factor (where an "n dimensional
    matrix" is n nested arrays)?
    greenflame, Jun 20, 2005
    #7
  8. greenflame

    RobG Guest

    greenflame wrote:
    > Everyone: So it is more efficient to fill in an empty array then to
    > copy one and shange the values?


    Yes, it's about 20% slower. You have to go through the array twice,
    doing most of what you have to do when mulitplying.

    > Also, since the idea has been brought
    > up, Is there a way good way to make an iff block that checks whether a
    > variable is a string, number, "1D Matrix", "2D Matrix, ... etc. A "1D
    > Matrix is just an array. A "2D Matrix" is an arry of arrays.


    A 'good' way? no. You have to checek each element. Your 'matrix' is
    just an object that holds arrays, it has no special methods to do
    matrix stuff (unless you create your own Matrix object, see below).

    Javascript only has 3 types: number, string and object. You can assume
    that your mulitply function gets something it can digest, or try to
    make it bullet-proof (which will add bloat and slowness). If you make
    the assumption that the calling function will only pass arrays or
    numbers, your work is much simpler and your function runs much faster.

    There is no native JavaScript 'matrix', though 'pointed ears' posted
    some code that creates a matrix object:

    <URL:http://groups-beta.google.com/group/comp.lang.javascript/browse_frm/thread/6244941b6459e84/75a08b121b84800c?q=RobG&rnum=59&hl=en#75a08b121b84800c>

    If you encounter an element that isn't a number (or a string that will
    convert to a number like '6' or '034' or such) or an array, what do you
    want to do? scalematrix() will return 'NaN', an alternative might be
    to return the element unmodified. But that will require an extra test
    and else statement (i.e. slowness). And what kind of matrix will
    contain non-number entries?

    The function that calls multiply should make sure whatever it passes
    fits the requirements of the function.

    >
    > Rob G: Does your multuplyArr function just multiply all the elements of
    > an "n dimensional matrix" by a certain factor (where an "n dimensional
    > matrix" is n nested arrays)?
    >


    Yes - but it's about 50% slower than using your cleaned-up multiply
    function, so if you know you have 1D or 2D arrays, don't use it. There
    may be more efficient algorithms, you'll need to search. I wrote it to
    be concise, I haven't had much luck making it more efficient.

    Try Wolfram research, they have lots of cool stuff based on working
    from first principles and present some neat algorthims for doing stuff.
    And it's presented in plain, simple terms (which suits me!).

    <URL:http://www.wolfram.com/>

    Checkout the links in the 'Site highlights' menu, lower right.

    Here is a version of the 'nDimension' multiplier that checks the input
    more thoroughly. If it's not a number or array, it just returns the
    thing unmodified (it's fractionally slower than the original).


    // Multiply an n dimension array
    function multiplyArr( A, n ) {
    if ( !isNaN(A) ) { return A*n; }
    if ( Array != A.constructor) { return A; }
    var i = A.length;
    var B = [];
    while ( i-- ) {
    B = multiplyArr( A, n );
    }
    return B;
    }

    However, a function designed specifically to multiply a 2D array runs
    in one third of the time (and 20% to 50% faster than scalematrix() ):

    function multiplyArr2D(A, n){
    var j, i = A.length;
    var B = [];
    while ( i-- ) {
    j = A.length ;
    B = [];
    while ( j-- ) {
    B[j] = A[j]*n;
    }
    }
    return B;
    }

    --
    Rob
    RobG, Jun 21, 2005
    #8
  9. On 21/06/2005 02:38, RobG wrote:

    [snip]

    > Javascript only has 3 types: number, string and object.


    You seem to be forgetting the Null, Undefined, and Boolean types. :p

    [snip]

    Mike

    --
    Michael Winter
    Replace ".invalid" with ".uk" to reply by e-mail.
    Michael Winter, Jun 21, 2005
    #9
  10. greenflame

    greenflame Guest

    ok. this helps quite a bit. Thanks =)
    greenflame, Jun 22, 2005
    #10
  11. JRS: In article <kcKte.2234$>, dated Tue, 21
    Jun 2005 01:38:24, seen in news:comp.lang.javascript, RobG
    <> posted :
    > However, a function designed specifically to multiply a 2D array runs
    > in one third of the time (and 20% to 50% faster than scalematrix() ):
    >
    >function multiplyArr2D(A, n){
    > var j, i = A.length;
    > var B = [];
    > while ( i-- ) {
    > j = A.length ;
    > B = [];
    > while ( j-- ) {
    > B[j] = A[j]*n;
    > }
    > }
    > return B;
    >}


    I think you could save a little more time by setting X = [] in the outer
    loop instead of B = [], using X for B in the inner loop. and
    following the inner loop by B = X. Likewise for A for which Y =
    A at the beginning of the outer loop. Untested.

    --
    © John Stockton, Surrey, UK. ?@merlyn.demon.co.uk Turnpike v4.00 IE 4 ©
    <URL:http://www.jibbering.com/faq/> JL/RC: FAQ of news:comp.lang.javascript
    <URL:http://www.merlyn.demon.co.uk/js-index.htm> jscr maths, dates, sources.
    <URL:http://www.merlyn.demon.co.uk/> TP/BP/Delphi/jscr/&c, FAQ items, links.
    Dr John Stockton, Jun 22, 2005
    #11
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Victor Lamberty

    I got it to compile but it did somthing strange

    Victor Lamberty, Jul 22, 2003, in forum: C Programming
    Replies:
    8
    Views:
    381
    Herbert Rosenau
    Jul 31, 2003
  2. Replies:
    4
    Views:
    237
    John Harrison
    Sep 26, 2005
  3. chak
    Replies:
    2
    Views:
    960
  4. Rogério Brito
    Replies:
    1
    Views:
    644
    Sean DiZazzo
    Sep 9, 2009
  5. Richard
    Replies:
    2
    Views:
    80
    Richard
    Dec 4, 2006
Loading...

Share This Page