i got a strange error message

G

greenflame

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.
 
I

Ivo

"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:
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 said:
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/
 
R

RobG

greenflame said:
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') );
 
M

Michael Winter

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
 
R

RobG

Michael said:
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;
}
 
M

Michael Winter

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
 
G

greenflame

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)?
 
R

RobG

greenflame said:
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...b84800c?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;
}
 
M

Michael Winter

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
 
D

Dr John Stockton

JRS: In article <[email protected]>, dated Tue, 21
Jun 2005 01:38:24, seen in RobG
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.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,008
Latest member
HaroldDark

Latest Threads

Top