Velocity Reviews > i got a strange error message

i got a strange error message

greenflame
Guest
Posts: n/a

 06-19-2005
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[i] *= 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[i][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.

Ivo
Guest
Posts: n/a

 06-20-2005
"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[i][j] *= factor; // This is "line 58"
> }
> }

<more snip>

Check for the existence of copy2darr with alert(copy2darr); or check its
return value, alert( output[i] && output[i][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

RobG
Guest
Posts: n/a

 06-20-2005
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[i] *= factor;

And put the new values into it:

output[i] = input[i]*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[i][j] *= factor; // This is "line 58"

output[i][j] = input[i][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[i] = input[i]*factor;
}
return output;
} else {
var output = [];
for (var i=0; i<input.length; i++) {
output[i] = [];
for (var j=0; j<input[i].length; j++) {
output[i][j] = input[i][j]*factor;
}
}
return output;
}
}

var A = [ [1, 2], [3, 4]];
var B = scalematrix(A, 5);
'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[i] = multiplyArr( A[i], 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

Michael Winter
Guest
Posts: n/a

 06-20-2005
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[i] = input[i]*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.

RobG
Guest
Posts: n/a

 06-20-2005
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[i] = input[i]*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[i] = input[i]*factor;
}
} else {
for (var i=0; i<input.length; i++) {
output[i] = [];
for (var j=0; j<input[i].length; j++) {
output[i][j] = input[i][j]*factor;
}
}
}
return output;
}

--
Rob

Michael Winter
Guest
Posts: n/a

 06-20-2005
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.

greenflame
Guest
Posts: n/a

 06-20-2005
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)?

RobG
Guest
Posts: n/a

 06-21-2005
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:

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/>

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[i] = multiplyArr( A[i], 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[i].length ;
B[i] = [];
while ( j-- ) {
B[i][j] = A[i][j]*n;
}
}
return B;
}

--
Rob

Michael Winter
Guest
Posts: n/a

 06-21-2005
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.

[snip]

Mike

--
Michael Winter
Replace ".invalid" with ".uk" to reply by e-mail.

greenflame
Guest
Posts: n/a

 06-22-2005
ok. this helps quite a bit. Thanks =)

 Posting Rules You may not post new threads You may not post replies You may not post attachments You may not edit your posts BB code is On Smilies are On [IMG] code is On HTML code is OffTrackbacks are On Pingbacks are On Refbacks are Off Forum Rules

 Similar Threads Thread Thread Starter Forum Replies Last Post Rogério Brito Python 1 09-09-2009 04:19 AM chak VHDL 2 01-28-2008 05:43 AM Leisure.201@gmail.com Javascript 1 04-28-2007 11:04 PM Robert Computer Support 2 10-23-2003 08:55 AM Robert Computer Support 2 10-16-2003 03:05 PM