2011-12-14 8 views
6

Hay una cosa que no me gusta en Matlab: a veces intenta ser demasiado inteligente. Por ejemplo, si tengo una raíz cuadrada negativa comoDesactivar el "comportamiento inteligente" en Matlab

a = -1; sqrt(a) 

Matlab no generará un error pero cambia en silencio a los números complejos. Lo mismo sucede con los logaritmos negativos. Esto puede llevar a errores difíciles de encontrar en un algoritmo más complicado.

Un problema similar es que Matlab "resuelve" sistemas lineales en silencio no cuadráticas como en el siguiente ejemplo:

A=eye(3,2); b=ones(3,1); x = A \ b 

Obviamente x no satisface A*x==b (Se resuelve un problema de mínimos cuadrados en lugar).

¿Hay alguna posibilidad de desactivar esas "funciones", o al menos dejar que Matlab imprima un mensaje de advertencia en estos casos? Eso realmente ayuda mucho en muchas situaciones.

+1

Me pregunto por qué las personas rechazaron esta pregunta. Creo que es totalmente legítimo preguntar esto. Además, estoy seguro de que hay muchas personas que perdieron el tiempo buscando errores sutiles debido al comportamiento descrito. – Boris

+1

La forma en que lee su pregunta puede sonar a algunos como "Realmente no leí la documentación que afirma que Matlab admite números complejos, y eso explica lo que hace el operador de barra invertida. ¿Puedo hacer que Matlab haga lo que falsamente asumí que haría, porque realmente estoy frustrado por mi incapacidad para leer la documentación? ". Aunque estoy en desacuerdo con usted sobre el problema con el operador de barra invertida, estoy de acuerdo en que los números complejos pueden ser indicativos de un problema. Por lo tanto, sería bueno si hubiera un "dbstop if complex" además de "dbstop if nan/inf" en el depurador. – Jonas

+0

@Jonas He intentado formular la pregunta de tal manera que el lector no tenga esta impresión, parece que he fallado :(. Tiene razón, la documentación es perfectamente clara al respecto. Creo que Matlab "sobreutiliza" el operador que podría conducir a errores y eso es malo.Otro que los principiantes suelen cometer incorrectamente es el siguiente: Una función (definida incorrectamente) como 'f = @ (x) x * ((x + 1)/x)' da el resultado 'f ([1,2]) = [1.6,3.2] 'mientras que la mayoría de los principiantes esperarían el resultado' [2,3] '. En un programa más grande, tales errores son muy difíciles de encontrar. – Boris

Respuesta

3

No creo que haya algo como "ser inteligente" en sus ejemplos. La raíz cuadrada de un número negativo es compleja. De manera similar, el operador de la división izquierda se define en Matlab como el cálculo de la pseudoinversión para las entradas no cuadradas.

Si tiene una aplicación que no debe devolver números complejos (¡tenga cuidado con los errores de punto flotante!), Entonces puede usar isreal para probar eso. Si no desea que el operador de división izquierda calcule el pseudoinverso, pruebe si A es cuadrado.

Como alternativa, si por alguna razón no puede realizar la validación de entrada, puede sobrecargar sqrt y \ para trabajar solo en números positivos y no calcular el pseudoinverso.

+0

Por supuesto, puedo verificar todos mis parámetros, pero en el 90% de los casos si mi entrada es real, la salida también debería ser real. Además, la solución de un sistema lineal es lo que las personas en la mayoría de los casos esperan cuando se utiliza el operador de barra invertida. Simplemente me gustaría activar el comportamiento por un parámetro. – Boris

+1

@ Boris: Parece que vamos a esto de manera muy diferente, entonces. En el 100% de los casos en que tomo la raíz cuadrada de un valor negativo, espero una producción compleja. Además, utilizo el operador de barra invertida exclusivamente para sistemas sobredeterminados (ya que el otro nunca debería ocurrir en mis aplicaciones). – Jonas

+1

@Boris: Desafortunadamente, no hay ningún conmutador incorporado que solo permita que se produzcan números reales en los cálculos (a menos que desee trabajar con todos los enteros). – Jonas

3

Necesita comprender todas las implicaciones de lo que está escribiendo y asegúrese de utilizar las funciones correctas si va a garantizar un buen código. Por ejemplo:

  • Para el primer caso, utilizar realsqrt lugar
  • Para el segundo caso, utilizar inv(A) * b lugar

O, alternativamente, incluir los controles adecuados antes/después de llamar a la incorporada en el funciones. Si necesita hacer esto cada vez, entonces siempre puede escribir sus propias funciones.

+0

El * ad hominem * no se ha llamado (y se ha eliminado), pero, de lo contrario, la solución no merece un voto negativo. +1 de mí para encontrar 'realsqrt'. – Jonas

+2

La propuesta 'inv (A) * b' es muy lenta en muchos casos (especialmente cuando A es escasa) y no debe utilizarse. – Boris

+0

@ Boris, estoy de acuerdo, pero si necesita una versión que solo funciona cuando A es cuadrada y no singular, entonces es la opción más simple. La mejor opción es que dos envuelvan la barra invertida en su propia función. – Nzbuu

Cuestiones relacionadas