Cursos
Módulo
Realización de operaciones básicas con números en C# - Training
Conozca los operadores y las técnicas que se usan para realizar operaciones matemáticas básicas en datos numéricos.
Este explorador ya no se admite.
Actualice a Microsoft Edge para aprovechar las características y actualizaciones de seguridad más recientes, y disponer de soporte técnico.
En esta sección se define el comportamiento de los distintos operadores de M.
Cuando una expresión contiene varios operadores, su precedencia controla el orden en el que se evalúan los operadores individuales. Por ejemplo, la expresión x + y * z
se evalúa como x + (y * z)
porque el operador *
tiene mayor precedencia que el operador binario +
. La precedencia de un operador se establece mediante la definición de su producción gramatical asociada. Por ejemplo, una instancia de additive-expression consta de una secuencia de multiplicative-expression separadas por los operadores +
o -
, por lo que se asigna a los operadores +
y -
una menor precedencia que la de los operadores *
y /
.
La producción parenthesized-expression se puede usar para cambiar el orden de precedencia predeterminado.
parenthesized-expression:
(
expresión )
Por ejemplo:
1 + 2 * 3 // 7
(1 + 2) * 3 // 9
En la tabla siguiente se resumen los operadores de M y se enumeran las categorías de operador en orden de prioridad, de mayor a menor. Los operadores de la misma categoría tienen la misma precedencia.
Categoría | Expresión | Descripción |
---|---|---|
Principal | i @i |
Expresión de identificador |
(x) | Expresión entre paréntesis | |
x[i] | Lookup | |
x{y} | Acceso a elementos | |
x(...) | Invocación de funciones | |
{x, y, ...} | Inicialización de listas | |
[ i = x, ... ] | Inicialización de registros | |
... | No implementado | |
Unario | +x | Identidad |
-x | Negación | |
not x |
Negación lógica | |
Metadatos | x meta y |
Asociación de metadatos |
Multiplicativa | x * y | Multiplicación |
x / y | División | |
Aditiva | x + y | Suma |
x - y | Resta | |
Relacional | x < y | Menor que |
x > y | Mayor que | |
x <= y | Menor o igual que | |
x >= y | Mayor o igual que | |
Igualdad | x = y | Igual |
x <> y | No igual a | |
Aserción de tipos | x as y |
Es compatible con tipos primitivos que aceptan valores NULL o error |
Conformidad de tipos | x is y |
Prueba la compatibilidad del tipo primitivo que acepta valores NULL |
Y lógico | x and y |
Conjunción de cortocircuito |
O lógico | x or y |
Disyunción de cortocircuito |
Coalesce | x ?? y |
Operador de fusión de NULL |
Cada valor tiene un valor de registro asociado que puede contener información adicional sobre el valor. Este registro se conoce como el registro de metadatos de un valor. Un registro de metadatos se puede asociar a cualquier tipo de valor, incluso null
. El resultado de este tipo de asociación es un nuevo valor con los metadatos especificados.
Un registro de metadatos es simplemente un registro normal y puede contener todos los campos y valores de un registro normal, y a su vez puede ser un registro de metadatos. La asociación de un registro de metadatos con un valor es "no intrusiva". No cambia el comportamiento del valor en las evaluaciones, excepto el de las que inspeccionan registros de metadatos de forma explícita.
Cada valor tiene un registro de metadatos predeterminado, incluso si no se ha especificado ninguno. El registro de metadatos predeterminado está vacío. En los ejemplos siguientes se muestra el acceso al registro de metadatos de un valor de texto mediante la función de la biblioteca estándar Value.Metadata
:
Value.Metadata( "Mozart" ) // []
Generalmente, los registros de metadatos no se conservan cuando un valor se usa con un operador o una función que crea un valor. Por ejemplo, si se concatenan dos valores de texto con el operador &
, los metadatos del valor de texto resultante es el registro vacío []
. Las expresiones siguientes son equivalentes:
"Amadeus " & ("Mozart" meta [ Rating = 5 ])
"Amadeus " & "Mozart"
Se pueden usar las funciones de biblioteca estándar Value.RemoveMetadata
y Value.ReplaceMetadata
para quitar todos los metadatos de un valor y para reemplazarlos (en lugar de combinarlos en metadatos que ya existan).
El único operador que devuelve resultados que contienen metadatos es el operador meta.
Los valores pueden ser cíclicos. Por ejemplo:
let l = {0, @l} in l
// {0, {0, {0, ... }}}
[A={B}, B={A}]
// [A = {{ ... }}, B = {{ ... }}]
Para controlar los valores cíclicos en M, la construcción de registros, listas y tablas es diferida. Un intento de construir un valor cíclico que no se beneficie de los valores estructurados intercalados en diferido produce un error:
[A=B, B=A]
// [A = Error.Record("Expression.Error",
// "A cyclic reference was encountered during evaluation"),
// B = Error.Record("Expression.Error",
// "A cyclic reference was encountered during evaluation"),
// ]
Algunos operadores de M se definen mediante la recursión estructural. Por ejemplo, la igualdad de registros y listas se define mediante la igualdad conjunta de los campos de registro y listas de elementos correspondientes, respectivamente.
Para los valores que no son cíclicos, la aplicación de recursión estructural genera una expansión finita del valor: los valores anidados compartidos se recorren repetidamente, pero el proceso de recursión siempre finaliza.
Un valor cíclico tiene una expansión infinita cuando se aplica la recursión estructural. En la semántica de M no hay disposiciones especiales para estas expansiones infinitas; un intento de comparar la igualdad de los valores cíclicos, por ejemplo, se quedará sin recursos y finalizará de forma excepcional.
Los operadores de selección y proyección permiten extraer datos de valores de lista y de registro.
Se puede seleccionar un valor de una lista o una tabla en función de su posición de base cero dentro de esa lista o tabla mediante item-access-expression.
item-access-expression:
item-selection
optional-item-selection
item-selection:
primary-expression {
item-selector }
optional-item-selection:
primary-expression {
item-selector } ?
item-selector:
expression
item-access-expression x{y}
devuelve lo siguiente:
En el caso de una lista x
y un número y
, el elemento de lista x
en la posición y
. El primer elemento de una lista se considera que tiene un índice ordinal de cero. Si la posición solicitada no existe en la lista, se produce un error.
En el caso de una tabla x
y un número y
, la fila de la tabla x
en la posición y
. La primera fila de una tabla se considera que tiene un índice ordinal de cero. Si la posición solicitada no existe en la tabla, se produce un error.
En el caso de una tabla x
y un registro y
, la fila de la tabla x
que coincide con los valores de campo de registro y
para los campos con nombres de campo que coinciden con los nombres de columna de tabla correspondientes. Si no hay ninguna fila coincidente única en la tabla, se produce un error.
Por ejemplo:
{"a","b","c"}{0} // "a"
{1, [A=2], 3}{1} // [A=2]
{true, false}{2} // error
#table({"A","B"},{{0,1},{2,1}}){0} // [A=0,B=1]
#table({"A","B"},{{0,1},{2,1}}){[A=2]} // [A=2,B=1]
#table({"A","B"},{{0,1},{2,1}}){[B=3]} // error
#table({"A","B"},{{0,1},{2,1}}){[B=1]} // error
item-access-expression también admite el formato x{y}?
, que devuelve null
cuando la posición (o coincidencia) y
no existe en la lista o la tabla x
. Si hay varias coincidencias para y
, se producirá un error.
Por ejemplo:
{"a","b","c"}{0}? // "a"
{1, [A=2], 3}{1}? // [A=2]
{true, false}{2}? // null
#table({"A","B"},{{0,1},{2,1}}){0}? // [A=0,B=1]
#table({"A","B"},{{0,1},{2,1}}){[A=2]}? // [A=2,B=1]
#table({"A","B"},{{0,1},{2,1}}){[B=3]}? // null
#table({"A","B"},{{0,1},{2,1}}){[B=1]}? // error
El acceso a los elementos no fuerza la evaluación de elementos de lista o tabla distintos del elemento al que se accede. Por ejemplo:
{ error "a", 1, error "c"}{1} // 1
{ error "a", error "b"}{1} // error "b"
Cuando se evalúa el operador de acceso a elementos x{y}
, sucede lo siguiente:
Se propagan los errores generados durante la evaluación de expresiones x
o y
.
La expresión x
genera un valor de lista o tabla.
La expresión y
genera un valor numérico o, si x
genera un valor de tabla, un valor de registro.
Si y
genera un valor numérico y el valor de y
es negativo, se genera un error con el código de motivo "Expression.Error"
.
Si y
genera un valor numérico y el valor de y
es mayor o igual que el recuento de x
, se genera un error con el código de motivo "Expression.Error"
, a menos que se use el formato de operador opcional x{y}?
, en cuyo caso se devuelve el valor null
.
Si x
genera un valor de tabla y y
genera un valor de registro, y no hay coincidencias con y
en x
, se genera un error con el código de motivo "Expression.Error"
, a menos que se use el formato de operador opcional x{y}?
, en cuyo caso se devuelve el valor null
.
Si x
genera un valor de tabla y y
genera un valor de registro, y hay varias coincidencias con y
en x
, se genera un error con el código de motivo "Expression.Error"
.
No se evalúa ningún elemento en x
que no sea el que se encuentra en la posición y
durante el proceso de selección del elemento. (Para las listas o tablas de streaming, se omiten los elementos o las filas anteriores a la posición y
, lo que puede provocar su evaluación, en función del origen de la lista o de la tabla).
field-access-expression se usa para seleccionar un valor de un registro o para proyectar un registro o una tabla en otro registro u otra tabla uno con menos campos o columnas, respectivamente.
field-access-expression:
field-selection
implicit-target-field-selection
proyección
implicit-target-projection
field-selection:
primary-expression field-selector
field-selector:
required-field-selector
optional-field-selector
required-field-selector:
[
field-name ]
optional-field-selector:
[
field-name ] ?
field-name:
generalized-identifier
quoted-identifier
implicit-target-field-selection:
field-selector
projection:
primary-expression required-projection
primary-expression optional-projection
required-projection:
[
required-selector-list ]
optional-projection:
[
required-selector-list ] ?
required-selector-list:
required-field-selector
required-selector-list ,
required-field-selector
implicit-target-projection:
required-projection
optional-projection
La forma más sencilla de acceso a campos es la selección de campos obligatorios. Usa el operador x[y]
para buscar un campo en un registro por nombre de campo. Si un campo y
no existe en x
, se produce un error. El formato x[y]?
se usa para realizar la selección de campos opcionales y devuelve null
si el campo solicitado no existe en el registro.
Por ejemplo:
[A=1,B=2][B] // 2
[A=1,B=2][C] // error
[A=1,B=2][C]? // null
El acceso colectivo de varios campos es compatible con los operadores para la proyección de registros obligatorios y la proyección de registros opcionales. El operador x[[y1],[y2],...]
proyecta el registro en un registro nuevo con menos campos (seleccionados por y1
, y2
, ...
). Si un campo seleccionado no existe, se produce un error. El operador x[[y1],[y2],...]
proyecta el registro en un registro nuevo con los campos seleccionados por y1
, y2
, ...
; si falta un campo, se usa null
en su lugar.
Por ejemplo:
[A=1,B=2][[B]] // [B=2]
[A=1,B=2][[C]] // error
[A=1,B=2][[B],[C]]? // [B=2,C=null]
Se admiten los formatos [y]
y [y]?
como una referencia abreviada al identificador _
(carácter de subrayado). Las dos expresiones siguientes son equivalentes:
[A]
_[A]
En el ejemplo siguiente se muestra el formato abreviado del acceso a campos:
let _ = [A=1,B=2] in [A] //1
También se admiten los formatos [[y1],[y2],...]
y [[y1],[y2],...]?
como abreviatura y las dos expresiones siguientes también son equivalentes:
[[A],[B]]
_[[A],[B]]
El formato abreviado es especialmente útil si se combina con la abreviatura each
, una manera de introducir una función de un único parámetro denominado _
(para obtener más información, vea Declaraciones simplificadas). Juntas, las dos abreviaturas simplifican las expresiones funcionales de orden superior comunes:
List.Select( {[a=1, b=1], [a=2, b=4]}, each [a] = [b])
// {[a=1, b=1]}
La expresión anterior es equivalente a la siguiente, más extensa y de aspecto críptico:
List.Select( {[a=1, b=1], [a=2, b=4]}, (_) => _[a] = _[b])
// {[a=1, b=1]}
El acceso a campos no fuerza la evaluación de otros distintos al que se accede. Por ejemplo:
[A=error "a", B=1, C=error "c"][B] // 1
[A=error "a", B=error "b"][B] // error "b"
Cuando se evalúa un operador de acceso a campos x[y]
, x[y]?
, x[[y]]
o x[[y]]?
, sucede lo siguiente:
Se propagan los errores generados durante la evaluación de la expresión x
.
Los errores que se producen al evaluar el campo y
están asociados permanentemente al campo y
y luego se propagan. Cualquier acceso futuro al campo y
producirá el mismo error.
La expresión x
genera un valor de registro o tabla, o bien se produce un error.
Si el identificador y
menciona a un campo que no existe en x
, se genera un error con el código de motivo "Expression.Error"
, a menos que se use el formato de operador opcional ...?
, en cuyo caso se devuelve el valor null
.
En el proceso de acceso a campos, no se evalúa ningún campo de x
que no sea el que menciona y
.
El registro de metadatos de un valor se modifica mediante el operador meta (x meta y
).
metadata-expression:
unary-expression
unary-expression meta
unary-expression
En el ejemplo siguiente se crea un valor de texto con un registro de metadatos mediante el operador meta
y, después, se accede al registro de metadatos del valor resultante mediante Value.Metadata
:
Value.Metadata( "Mozart" meta [ Rating = 5 ] )
// [Rating = 5 ]
Value.Metadata( "Mozart" meta [ Rating = 5 ] )[Rating]
// 5
Cuando se aplica el operador de combinación de metadatos x meta y
, sucede lo siguiente:
Se propagan los errores que se producen al evaluar las expresiones x
o y
.
La expresión y
debe ser un registro, o bien se produce un error con el código de motivo "Expression.Error"
.
El registro de metadatos resultante es el de x
combinado con y
. (Para obtener la semántica de la combinación de registros, vea Combinación de registros).
El valor resultante es el de la expresión x
, sin sus metadatos, con el registro de metadatos recién calculado adjunto.
Se pueden usar las funciones de biblioteca estándar Value.RemoveMetadata
y Value.ReplaceMetadata
para quitar todos los metadatos de un valor y para reemplazarlos (en lugar de combinarlos en metadatos que ya existan). Las expresiones siguientes son equivalentes:
x meta y
Value.ReplaceMetadata(x, Value.Metadata(x) & y)
Value.RemoveMetadata(x) meta (Value.Metadata(x) & y)
El operador de igualdad =
se usa para determinar si dos valores son iguales. El operador de desigualdad <>
se usa para determinar si dos valores no son iguales.
equality-expression:
relational-expression
relational-expression =
equality-expression
relational-expression <>
equality-expression
Por ejemplo:
1 = 1 // true
1 = 2 // false
1 <> 1 // false
1 <> 2 // true
null = true // false
null = null // true
Los metadatos no forman parte de la comparación de igualdad o desigualdad. Por ejemplo:
(1 meta [ a = 1 ]) = (1 meta [ a = 2 ]) // true
(1 meta [ a = 1 ]) = 1 // true
Cuando se aplican los operadores de igualdad x = y
y x <> y
, sucede lo siguiente:
Se propagan los errores que se producen al evaluar las expresiones x
o y
.
El operador =
tiene un resultado de true
si los valores son iguales y de false
en caso contrario.
El operador <>
tiene un resultado de false
si los valores son iguales y de true
en caso contrario.
Los registros de metadatos no se incluyen en la comparación.
Si los valores generados al evaluar las expresiones x
e y
no tienen el mismo tipo de valor, los valores no son iguales.
Si los valores generados al evaluar las expresiones x
e y
son el mismo tipo de valor, hay reglas específicas para determinar si son iguales, como se define a continuación.
Lo siguiente se cumple siempre:
(x = y) = not (x <> y)
Los operadores de igualdad se definen para los tipos siguientes:
null
solo es igual a sí mismo. null = null // true
null = true // false
null = false // false
true
y false
solo son iguales a sí mismos. Por ejemplo: true = true // true
false = false // true
true = false // false
true = 1 // false
Los números se comparan con la precisión especificada:
Si uno es #nan
, los números no son los mismos.
Si ninguno es #nan
, los números se comparan mediante una comparación de bits del valor numérico.
#nan
es el único valor que no es igual a sí mismo.
Por ejemplo:
1 = 1, // true
1.0 = 1 // true
2 = 1 // false
#nan = #nan // false
#nan <> #nan // true
Dos duraciones son iguales si representan el mismo número de tics de 100 nanosegundos.
Dos horas son iguales si las magnitudes de sus partes (hora, minuto, segundo) son iguales.
Dos fechas son iguales si las magnitudes de sus partes (año, mes, día) son iguales.
Dos valores de fecha y hora son iguales si las magnitudes de sus partes (año, mes, día, hora, minuto, segundo) son iguales.
Dos valores de fecha, hora y zona horaria son iguales si los valores de fecha y hora UTC correspondientes son iguales. Para llegar a la fecha y hora UTC correspondiente, el desplazamiento de horas/minutos se resta del componente de fecha y hora del valor de fecha, hora y zona horaria.
Dos valores de texto son iguales si al usar una comparación ordinal, con distinción de mayúsculas y minúsculas y sin distinción de referencia cultural tienen la misma longitud y caracteres iguales en las posiciones correspondientes.
Dos valores de lista son iguales si se cumple todo lo siguiente:
Las dos listas contienen el mismo número de elementos.
Los valores de cada elemento posicionalmente correspondiente en las listas son iguales. Esto significa que las listas no solo deben contener elementos iguales, sino que deben estar en el mismo orden.
Por ejemplo:
{1, 2} = {1, 2} // true
{2, 1} = {1, 2} // false
{1, 2, 3} = {1, 2} // false
Dos registros son iguales si se cumple todo lo siguiente:
El número de campos es el mismo.
Cada nombre de campo de un registro también está presente en el otro registro.
El valor de cada campo de un registro es igual al campo con el mismo nombre del otro registro.
Por ejemplo:
[ A = 1, B = 2 ] = [ A = 1, B = 2 ] // true
[ B = 2, A = 1 ] = [ A = 1, B = 2 ] // true
[ A = 1, B = 2, C = 3 ] = [ A = 1, B = 2 ] // false
[ A = 1 ] = [ A = 1, B = 2 ] // false
Dos tablas son iguales si se cumple todo lo siguiente:
El número de columnas es el mismo.
Cada nombre de columna de una tabla también está presente en la otra.
El número de filas es el mismo.
Cada fila tiene los mismos valores en las celdas correspondientes.
Por ejemplo:
#table({"A","B"},{{1,2}}) = #table({"A","B"},{{1,2}}) // true
#table({"A","B"},{{1,2}}) = #table({"X","Y"},{{1,2}}) // false
#table({"A","B"},{{1,2}}) = #table({"B","A"},{{2,1}}) // true
Un valor de función es igual a sí mismo, pero puede o no ser igual a otro valor de función. Si dos valores de función se consideran iguales, se comportarán de la misma manera cuando se invocan.
Dos valores de función dados siempre tendrán la misma relación de igualdad.
Un valor de tipo es igual a sí mismo, pero puede o no ser igual a otro valor de tipo. Si dos valores de tipo se consideran iguales, se comportarán de la misma manera cuando se consulta su compatibilidad.
Dos valores de tipo dados siempre tendrán la misma relación de igualdad.
Los operadores <
, >
, <=
y >=
se denominan operadores relacionales.
relational-expression:
additive-expression
additive-expression <
relational-expression
additive-expression >
relational-expression
additive-expression <=
relational-expression
additive-expression >=
relational-expression
Estos operadores se usan para determinar la relación de ordenación relativa entre dos valores, como se muestra en la tabla siguiente:
Operación | Resultado |
---|---|
x < y |
true si x es menor que y , false en caso contrario |
x > y |
true si x es mayor que y , false en caso contrario |
x <= y |
true si x es menor o igual que y , false en caso contrario |
x >= y |
true si x es mayor o igual que y , false en caso contrario |
Por ejemplo:
0 <= 1 // true
null < 1 // null
null <= null // null
"ab" < "abc" // true
#nan >= #nan // false
#nan <= #nan // false
Cuando se evalúa una expresión que contiene los operadores relacionales, sucede lo siguiente:
Se propagan los errores que se producen al evaluar las expresiones de operando x
o y
.
Los valores generados al evaluar las expresiones x
e y
deben ser de binario, fecha, fecha y hora, fecha, hora y zona horaria, duración, lógicos, null, texto o de hora. De lo contrario, se genera un error con el código de motivo "Expression.Error"
.
Ambos operandos deben ser el mismo tipo de valor o null
. De lo contrario, se genera un error con el código de motivo "Expression.Error"
.
Si uno o los dos operandos son null
, el resultado es el valor null
.
Dos archivos binarios se comparan byte por byte.
Para comparar dos fechas se comparan sus partes de año y, si son iguales, sus partes de mes y, si son iguales, sus partes de día.
Para comparar dos valores de fecha y hora se comparan sus partes de año y, si son iguales, sus partes de mes y, si son iguales, sus partes de día y, si son iguales, sus partes de hora y, si son iguales, sus partes de minuto y, si son iguales, sus partes de segundo.
Para comparar dos valores de fecha, hora y zona horaria, se normalizan a la hora UTC restando su desplazamiento por hora/minuto y comparando después sus componentes de fecha y hora.
Dos duraciones se comparan según el número total de tics de 100 nanosegundos que representan.
Se comparan dos elementos lógicos de forma que true
se considera mayor que false
.
Dos números x
e y
se comparan según las reglas del estándar IEEE 754:
Si alguno de los operandos es #nan
, el resultado es false
para todos los operadores relacionales.
Cuando ninguno de los operandos es #nan
, los operadores comparan los valores de los dos operandos de punto flotante con respecto a la ordenación -∞ < -max < ... < -min < -0.0 = +0.0 < +min < ... < +max < +∞
, donde "min" y "max" son los valores finitos positivos más pequeños y más grandes que se pueden representar. En M, -∞ y +∞ se denominan "-#infinity
" y "#infinity
".
Los efectos importantes de este orden son:
Los ceros negativos y positivos se consideran iguales.
Un valor -#infinity
se considera menor que el resto de los valores numéricos, pero es igual a otro -#infinity
.
Un valor #infinity
se considera mayor que el resto de los valores numéricos, pero es igual a otro #infinity
.
Se comparan dos textos mediante una comparación sin distinción entre mayúsculas y minúsculas, sin distinción entre mayúsculas y minúsculas.
Para comparar dos horas se comparan sus partes de hora y, si son iguales, sus partes de minuto y, si son iguales, sus partes de segundo.
Los operadores and
y or
se denominan operadores lógicos condicionales.
logical-or-expression:
logical-and-expression
logical-and-expression or
logical-or-expression
logical-and-expression:
is-expression
is-expression and
logical-and-expression
El operador or
devuelve true
cuando al menos uno de sus operandos es true
. El operando derecho se evalúa solo si el operando izquierdo no es true
.
El operador and
devuelve false
cuando al menos uno de sus operandos es false
. El operando derecho se evalúa solo si el operando izquierdo no es false
.
A continuación se muestran las tablas de verdad para los operadores or
y and
, con el resultado de evaluar la expresión de operando de la izquierda en el eje vertical y el de evaluar la expresión de operando de la derecha en el horizontal.
and |
true |
false |
null |
error |
---|---|---|---|---|
true |
true |
false |
null |
error |
false |
false |
false |
false |
false |
null |
null |
false |
null |
error |
error |
error |
error |
error |
error |
or |
true |
false |
null |
error |
---|---|---|---|---|
or |
true |
false |
null |
error |
true |
true |
true |
true |
true |
false |
true |
false |
null |
error |
null |
true |
null |
null |
error |
error |
error |
error |
error |
error |
Cuando se evalúa una expresión que contiene operadores lógicos condicionales, sucede lo siguiente:
Se propagan los errores que se producen al evaluar las expresiones x
o y
.
Los operadores lógicos condicionales se definen antes que los tipos logical
y null
. Si los valores de operando no son de esos tipos, se genera un error con el código de motivo "Expression.Error"
.
El resultado es un valor lógico.
En la expresión x
o y
, se evaluará la expresión y
solo si x
no se evalúa como true
.
En la expresión x
e y
, se evaluará la expresión y
solo si x
no se evalúa como false
.
Las dos últimas propiedades proporcionan a los operadores lógicos condicionales su calificación de "condicionales"; las propiedades también se denominan "cortocircuito". Estas propiedades son útiles para escribir predicados protegidos. Por ejemplo, las expresiones siguientes son equivalentes:
d <> 0 and n/d > 1 if d <> 0 then n/d > 1 else false
Los operadores +
, -
, *
y /
son los operadores aritméticos.
additive-expression:
multiplicative-expression
additive-expression +
multiplicative-expression
additive-expression -
multiplicative-expression
expresión-multiplicativa:
metadata- expression
multiplicative-expression *
metadata-expression
multiplicative-expression /
metadata-expression
En M, los números se almacenan con diversas representaciones para conservar tanta información como sea posible sobre los números procedentes de diversos orígenes. Los números solo se convierten de una representación a otra según sea necesario para los operadores que se les aplica. En M se admiten dos precisiones:
Precisión | Semántica |
---|---|
Precision.Decimal |
Representación decimal de 128 bits con un intervalo de ±1,0 x 10-28 a ±7,9 x 1028 and 28-29 dígitos significativos. |
Precision.Double |
Representación científica con mantisa y exponente; se ajusta al estándar aritmético IEEE 754 de doble precisión de 64 bits IEEE 754-2008. |
Para realizar operaciones aritméticas, se elige una precisión, se convierten los dos operandos a esa precisión (si es necesario), después se realiza la operación real y, por último, se devuelve un número con la precisión elegida.
Los operadores aritméticos integrados (+
, -
, *
, /
) usan precisión doble. Las funciones de la biblioteca estándar (Value.Add
, Value.Subtract
, Value.Multiply
, Value.Divide
) se pueden usar para solicitar estas operaciones con un modelo de precisión específico.
El desbordamiento numérico no es posible: #infinity
o -#infinity
representan valores de magnitudes demasiado grandes para representarlos.
El subdesbordamiento numérico no es posible: 0
y -0
representan valores de magnitudes demasiado pequeñas para representarlos.
El valor especial de IEEE 754 #nan
(NaN: No es un número) se usa para cubrir los casos aritméticos no válidos, como la división de cero por cero.
Para realizar la conversión de precisión decimal a doble se redondean los números decimales al valor doble equivalente más próximo.
Para realizar la conversión de precisión doble a decimal se redondean los números dobles al valor decimal equivalente más cercano y, si es necesario, se desborda a valores #infinity
o -#infinity
.
La interpretación del operador de suma (x + y
) depende del tipo de valor de las expresiones x e y evaluadas, como se indica a continuación:
x | y | Resultado | Interpretación |
---|---|---|---|
type number |
type number |
type number |
Suma numérica |
type number |
null |
null |
|
null |
type number |
null |
|
type duration |
type duration |
type duration |
Suma numérica de magnitudes |
type duration |
null |
null |
|
null |
type duration |
null |
|
type datetime |
type duration |
type datetime |
Desplazamiento de fecha y hora según la duración |
type duration |
type datetime |
type datetime |
|
type datetime |
null |
null |
|
null |
type datetime |
null |
En la tabla, type
datetime representa type date
, type datetime
, type datetimezone
o type time
. Al sumar una duración y un valor de algún tipo datetime, el valor resultante es del mismo tipo.
Para otras combinaciones de valores que no sean las enumeradas en la tabla, se genera un error con el código de motivo "Expression.Error"
. Cada combinación se describe en las secciones siguientes.
Se propagan los errores que se producen al evaluar cualquiera de los operandos.
La suma de dos números se calcula mediante el operador de suma, lo que genera un número.
Por ejemplo:
1 + 1 // 2
#nan + #infinity // #nan
El operador de suma +
en números usa la precisión doble; la función de la biblioteca estándar Value.Add
se puede usar para especificar la precisión decimal. Al calcular una suma de números sucede lo siguiente:
La suma en precisión doble se calcula de acuerdo a las reglas aritméticas de IEEE 754 de precisión doble binaria de 64 bits IEEE 754-2008. En la tabla siguiente se enumeran los resultados de todas las posibles combinaciones de valores finitos distintos de cero, ceros, infinitos y NaN. En la tabla, x
e y
son valores finitos distintos de cero y z
es el resultado de x + y
. Si x
e y
tienen la misma magnitud pero signos opuestos, z
es cero positivo. Si x + y
es demasiado grande para representarse en el tipo de destino, z
es un infinito con el mismo signo que x + y
.
+ | y | +0 | -0 | +∞ | -∞ | NaN |
---|---|---|---|---|---|---|
x | z | x | x | +∞ | -∞ | NaN |
+0 | y | +0 | +0 | +∞ | -∞ | NaN |
-0 | y | +0 | -0 | +∞ | -∞ | NaN |
+∞ | +∞ | +∞ | +∞ | +∞ | NaN | NaN |
-∞ | -∞ | -∞ | -∞ | NaN | -∞ | NaN |
NaN | NaN | NaN | NaN | NaN | NaN | NaN |
La suma en precisión decimal se calcula sin perder precisión. La escala del resultado es la mayor de las escalas de los dos operandos.
La suma de dos duraciones es la duración que representa la suma del número de tics de 100 nanosegundos representados por las duraciones. Por ejemplo:
#duration(2,1,0,15.1) + #duration(0,1,30,45.3)
// #duration(2, 2, 31, 0.4)
Se puede sumar un valor datetime x
y una duración y
con x + y
para calcular un nuevo valor datetime cuya distancia con respecto a x
en una escala de tiempo lineal sea exactamente la magnitud de y
. Aquí, datetime equivale a Date
, DateTime
, DateTimeZone
o Time
, y un resultado no NULL será del mismo tipo. El desplazamiento de fecha y hora por duración se puede calcular de la manera siguiente:
Si se especifican los días de la fecha y hora desde el valor de época, se construye un nuevo objeto datetime con los elementos de información siguientes:
Se calcula un nuevo número de días desde la época, equivalente a dividir la magnitud de y por el número de tics de 100 nanosegundos en un período de 24 horas, se trunca la parte decimal del resultado y se suma este valor a los días de x desde la época.
Se calcula un nuevo tic desde la medianoche equivalente a sumar la magnitud de y a los tics de x desde la medianoche, módulo el número de tics de 100 nanosegundos en un período de 24 horas. Si x no especifica un valor para los tics desde la medianoche, se supone un valor de 0.
Se copia el valor de x para el desplazamiento de minutos con respecto a la hora UTC sin modificar.
Si no se especifican los días de la fecha y hora desde el valor de época, se construye un nuevo objeto datetime con los elementos de información siguientes:
Se calcula un nuevo tic desde la medianoche equivalente a sumar la magnitud de y a los tics de x desde la medianoche, módulo el número de tics de 100 nanosegundos en un período de 24 horas. Si x no especifica un valor para los tics desde la medianoche, se supone un valor de 0.
Se copian los valores de x de los días desde la época y el desplazamiento de minutos con respecto a la hora UTC sin modificar.
En los ejemplos siguientes se muestra cómo calcular la suma temporal absoluta cuando la fecha y hora especifica los días desde la época:
#date(2010,05,20) + #duration(0,8,0,0)
//#datetime( 2010, 5, 20, 8, 0, 0 )
//2010-05-20T08:00:00
#date(2010,01,31) + #duration(30,08,0,0)
//#datetime(2010, 3, 2, 8, 0, 0)
//2010-03-02T08:00:00
#datetime(2010,05,20,12,00,00,-08) + #duration(0,04,30,00)
//#datetime(2010, 5, 20, 16, 30, 0, -8, 0)
//2010-05-20T16:30:00-08:00
#datetime(2010,10,10,0,0,0,0) + #duration(1,0,0,0)
//#datetime(2010, 10, 11, 0, 0, 0, 0, 0)
//2010-10-11T00:00:00+00:00
En el ejemplo siguiente se muestra cómo calcular el desplazamiento de fecha y hora por duración para una hora concreta:
#time(8,0,0) + #duration(30,5,0,0)
//#time(13, 0, 0)
//13:00:00
La interpretación del operador de resta (x - y
) depende del tipo de valor de las expresiones x
e y
evaluadas, como se indica a continuación:
x | Y | Resultado | Interpretación |
---|---|---|---|
type number |
type number |
type number |
Diferencia numérica |
type number |
null |
null |
|
null |
type number |
null |
|
type duration |
type duration |
type duration |
Diferencia numérica de magnitudes |
type duration |
null |
null |
|
null |
type duration |
null |
|
type datetime |
type datetime |
type duration |
Duración entre fechas y horas |
type datetime |
type duration |
type datetime |
Desplazamiento de fecha y hora según la duración negada |
type datetime |
null |
null |
|
null |
type datetime |
null |
En la tabla, type
datetime representa type date
, type datetime
, type datetimezone
o type time
. Al restar una duración de un valor de algún tipo datetime, el valor resultante es del mismo tipo.
Para otras combinaciones de valores que no sean las enumeradas en la tabla, se genera un error con el código de motivo "Expression.Error"
. Cada combinación se describe en las secciones siguientes.
Se propagan los errores que se producen al evaluar cualquiera de los operandos.
La diferencia entre dos números se calcula mediante el operador de resta, lo que genera un número. Por ejemplo:
1 - 1 // 0
#nan - #infinity // #nan
El operador de resta -
en números usa la precisión doble; la función de la biblioteca estándar Value.Subtract
se puede usar para especificar la precisión decimal. Al calcular una diferencia de números sucede lo siguiente:
La diferencia en precisión doble se calcula de acuerdo a las reglas aritméticas de IEEE 754 de precisión doble binaria de 64 bits IEEE 754-2008. En la tabla siguiente se enumeran los resultados de todas las posibles combinaciones de valores finitos distintos de cero, ceros, infinitos y NaN. En la tabla, x
e y
son valores finitos distintos de cero y z
es el resultado de x - y
. Si x
e y
son iguales, z
es cero positivo. Si x - y
es demasiado grande para representarse en el tipo de destino, z
es un infinito con el mismo signo que x - y
.
- | y | +0 | -0 | +∞ | -∞ | NaN |
---|---|---|---|---|---|---|
x | z | x | x | -∞ | +∞ | NaN |
+0 | -y | +0 | +0 | -∞ | +∞ | NaN |
-0 | -y | -0 | +0 | -∞ | +∞ | NaN |
+∞ | +∞ | +∞ | +∞ | NaN | +∞ | NaN |
-∞ | -∞ | -∞ | -∞ | -∞ | NaN | NaN |
NaN | NaN | NaN | NaN | NaN | NaN | NaN |
La diferencia en precisión decimal se calcula sin perder precisión. La escala del resultado es la mayor de las escalas de los dos operandos.
La diferencia de dos duraciones es la duración que representa la diferencia entre el número de tics de 100 nanosegundos representados por cada duración. Por ejemplo:
#duration(1,2,30,0) - #duration(0,0,0,30.45)
// #duration(1, 2, 29, 29.55)
Se puede restar un valor datetime x
y una duración y
con x - y
para calcular un nuevo valor datetime. Aquí, datetime representa date
, datetime
, datetimezone
o time
. El valor datetime resultante tiene una distancia con respecto a x
en una escala de tiempo lineal que es exactamente la magnitud de y
, en la dirección opuesta al signo de y
. La resta de duraciones positivas genera resultados anteriores en el tiempo con respecto a x
, mientras que la resta de valores negativos genera resultados posteriores en el tiempo.
#date(2010,05,20) - #duration(00,08,00,00)
//#datetime(2010, 5, 19, 16, 0, 0)
//2010-05-19T16:00:00
#date(2010,01,31) - #duration( 30,08,00,00)
//#datetime(2009, 12, 31, 16, 0, 0)
//2009-12-31T16:00:00
Se pueden restar dos valores datetime t
y u
con t - u
para calcular la duración entre ellos. Aquí, datetime representa date
, datetime
, datetimezone
o time
. La duración que se genera al restar u
de t
debe producir t
cuando se suma a u
.
#date(2010,01,31) - #date(2010,01,15)
// #duration(16,00,00,00)
// 16.00:00:00
#date(2010,01,15)- #date(2010,01,31)
// #duration(-16,00,00,00)
// -16.00:00:00
#datetime(2010,05,20,16,06,00,-08,00) -
#datetime(2008,12,15,04,19,19,03,00)
// #duration(521,22,46,41)
// 521.22:46:41
Al restar t - u
cuando u > t
se genera una duración negativa:
#time(01,30,00) - #time(08,00,00)
// #duration(0, -6, -30, 0)
Cuando se restan dos valores datetime mediante t - u
, sucede lo siguiente:
La interpretación del operador de multiplicación (x * y
) depende del tipo de valor de las expresiones x e y evaluadas, como se indica a continuación:
X | Y | Resultado | Interpretación |
---|---|---|---|
type number |
type number |
type number |
Producto numérico |
type number |
null |
null |
|
null |
type number |
null |
|
type duration |
type number |
type duration |
Múltiplo de duración |
type number |
type duration |
type duration |
Múltiplo de duración |
type duration |
null |
null |
|
null |
type duration |
null |
Para otras combinaciones de valores que no sean las enumeradas en la tabla, se genera un error con el código de motivo "Expression.Error"
. Cada combinación se describe en las secciones siguientes.
Se propagan los errores que se producen al evaluar cualquiera de los operandos.
El producto de dos números se calcula mediante el operador de multiplicación, lo que genera un número. Por ejemplo:
2 * 4 // 8
6 * null // null
#nan * #infinity // #nan
El operador de multiplicación *
en números usa la precisión doble; la función de la biblioteca estándar Value.Multiply
se puede usar para especificar la precisión decimal. Al calcular un producto de números sucede lo siguiente:
El producto en precisión doble se calcula de acuerdo a las reglas aritméticas de IEEE 754 de precisión doble binaria de 64 bits IEEE 754-2008. En la tabla siguiente se enumeran los resultados de todas las posibles combinaciones de valores finitos distintos de cero, ceros, infinitos y NaN. En la tabla, x
e y
son valores finitos positivos. z
es el resultado de x * y
. Si el resultado es demasiado grande para el tipo de destino, z
es infinito. Si el resultado es demasiado pequeño para el tipo de destino, z
es cero.
* | +y | -y | +0 | -0 | +∞ | -∞ | NaN |
---|---|---|---|---|---|---|---|
+x | +z | -Z | +0 | -0 | +∞ | -∞ | NaN |
-x | -Z | +z | -0 | +0 | -∞ | +∞ | NaN |
+0 | +0 | -0 | +0 | -0 | NaN | NaN | NaN |
-0 | -0 | +0 | -0 | +0 | NaN | NaN | NaN |
+∞ | +∞ | -∞ | NaN | NaN | +∞ | -∞ | NaN |
-∞ | -∞ | +∞ | NaN | NaN | -∞ | +∞ | NaN |
NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
El producto en precisión decimal se calcula sin perder precisión. La escala del resultado es la mayor de las escalas de los dos operandos.
El producto de una duración y un número es la duración que representa el número de tics de 100 nanosegundos representados por el operando de duración multiplicado por el de número. Por ejemplo:
#duration(2,1,0,15.1) * 2
// #duration(4, 2, 0, 30.2)
La interpretación del operador de división (x / y
) depende del tipo de valor de las expresiones x
e y
evaluadas, como se indica a continuación:
X | Y | Resultado | Interpretación |
---|---|---|---|
type number |
type number |
type number |
Cociente numérico |
type number |
null |
null |
|
null |
type number |
null |
|
type duration |
type number |
type duration |
Fracción de duración |
type duration |
type duration |
type number |
Cociente numérico de duraciones |
type duration |
null |
null |
|
null |
type duration |
null |
Para otras combinaciones de valores que no sean las enumeradas en la tabla, se genera un error con el código de motivo "Expression.Error"
. Cada combinación se describe en las secciones siguientes.
Se propagan los errores que se producen al evaluar cualquiera de los operandos.
El cociente de dos números se calcula mediante el operador de división, lo que genera un número. Por ejemplo:
8 / 2 // 4
8 / 0 // #infinity
0 / 0 // #nan
0 / null // null
#nan / #infinity // #nan
El operador de división /
en números usa la precisión doble; la función de la biblioteca estándar Value.Divide
se puede usar para especificar la precisión decimal. Al calcular un cociente de números sucede lo siguiente:
El cociente en precisión doble se calcula de acuerdo a las reglas aritméticas de IEEE 754 de precisión doble binaria de 64 bits IEEE 754-2008. En la tabla siguiente se enumeran los resultados de todas las posibles combinaciones de valores finitos distintos de cero, ceros, infinitos y NaN. En la tabla, x
e y
son valores finitos positivos. z
es el resultado de x / y
. Si el resultado es demasiado grande para el tipo de destino, z
es infinito. Si el resultado es demasiado pequeño para el tipo de destino, z
es cero.
/ | +y | -y | +0 | -0 | +∞ | -∞ | NaN |
---|---|---|---|---|---|---|---|
+x | +z | -Z | +∞ | -∞ | +0 | -0 | NaN |
-x | -Z | +z | -∞ | +∞ | -0 | +0 | NaN |
+0 | +0 | -0 | NaN | NaN | +0 | -0 | NaN |
-0 | -0 | +0 | NaN | NaN | -0 | +0 | NaN |
+∞ | +∞ | -∞ | +∞ | -∞ | NaN | NaN | NaN |
-∞ | -∞ | +∞ | -∞ | +∞ | NaN | NaN | NaN |
NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
La suma en precisión decimal se calcula sin perder precisión. La escala del resultado es la mayor de las escalas de los dos operandos.
El cociente de dos duraciones es el número que representa el cociente del número de tics de 100 nanosegundos representados por las duraciones. Por ejemplo:
#duration(2,0,0,0) / #duration(0,1,30,0)
// 32
El cociente de una duración x
y un número y
es la duración que representa el cociente del número de tics de 100 nanosegundos representados por la duración x
y el número y
. Por ejemplo:
#duration(2,0,0,0) / 32
// #duration(0,1,30,0)
El operador de combinación (x & y
) se define en los tipos de valores siguientes:
X | Y | Resultado | Interpretación |
---|---|---|---|
type text |
type text |
type text |
Concatenación |
type text |
null |
null |
|
null |
type text |
null |
|
type date |
type time |
type datetime |
Combinar |
type date |
null |
null |
|
null |
type time |
null |
|
type list |
type list |
type list |
Concatenación |
type record |
type record |
type record |
Combinar |
type table |
type table |
type table |
Concatenación |
Dos valores de texto, dos listas o dos tablas se pueden concatenar mediante x & y
.
En el ejemplo siguiente se muestra la concatenación de valores de texto:
"AB" & "CDE" // "ABCDE"
En el ejemplo siguiente se muestra la concatenación de listas:
{1, 2} & {3} // {1, 2, 3}
Cuando se concatenan dos valores mediante x & y
, sucede lo siguiente:
Se propagan los errores que se producen al evaluar las expresiones x
o y
.
No se propaga ningún error si un elemento de x
o y
contiene un error.
El resultado de concatenar dos valores de texto es un valor de texto que contiene el valor de x inmediatamente seguido de y. Si alguno de los operandos es NULL y el otro es un valor de texto, el resultado es NULL.
El resultado de la concatenación de dos listas es una lista que contiene todos los elementos de x
seguidos de todos los elementos de y
.
El resultado de la concatenación de dos tablas es una tabla que tiene la unión de las columnas de las dos tablas de operandos. Se conserva el orden de las columnas de x
, seguido de las columnas que solo aparecen en y
, para conservar su orden relativo. En el caso de las columnas que solo aparecen en uno de los operandos, se usa null
para rellenar los valores de celda para el otro operando.
Dos registros se pueden combinar mediante x & y
, lo que genera un registro que incluye los campos de x
e y
.
En los ejemplos siguientes se muestra la combinación de registros:
[ x = 1 ] & [ y = 2 ] // [ x = 1, y = 2 ]
[ x = 1, y = 2 ] & [ x = 3, z = 4 ] // [ x = 3, y = 2, z = 4 ]
Cuando se combinan dos registros mediante x + y
, sucede lo siguiente:
Se propagan los errores que se producen al evaluar las expresiones x
o y
.
Si un campo aparece en x
e y
, se usa el valor de y
.
El orden de los campos en el registro resultante es el de x
, seguido de los campos de y
que no forman parte de x
, en el mismo orden en que aparecen en y
.
La combinación de registros no provoca la evaluación de los valores.
No se produce ningún error porque un campo contenga un error.
El resultado es un registro.
Una fecha x
se puede combinar con una hora y
mediante x & y
, lo que genera un valor de fecha y hora que combina las partes de x
e y
.
En el ejemplo siguiente se muestra cómo combinar una fecha y una hora:
#date(2013,02,26) & #time(09,17,00)
// #datetime(2013,02,26,09,17,00)
Cuando se combinan dos registros mediante x + y
, sucede lo siguiente:
Se propagan los errores que se producen al evaluar las expresiones x
o y
.
El resultado es un valor de fecha y hora.
Los operadores +
, -
y not
son operadores unarios.
unary-expression:
type-expression
+
expresión unaria
-
expresión unaria
not
expresión unaria
El operador unario más (+x
) se define para los tipos de valores siguientes:
X | Resultado | Interpretación |
---|---|---|
type number |
type number |
Suma unaria |
type duration |
type duration |
Suma unaria |
null |
`null |
Para otros valores, se genera un error con el código de motivo "Expression.Error"
.
El operador unario más permite aplicar un +
signo a un valor de número, fecha y hora, o NULL. El resultado es ese mismo valor. Por ejemplo:
+ - 1 // -1
+ + 1 // 1
+ #nan // #nan
+ #duration(0,1,30,0) // #duration(0,1,30,0)
Al evaluar el operador unario más +x
, sucede lo siguiente:
Se propagan los errores que se producen al evaluar x
.
Si el resultado de evaluar x
no es un valor numérico, se genera un error con el código de motivo "Expression.Error"
.
El operador unario menos (-x
) se define para los tipos de valores siguientes:
X | Resultado | Interpretación |
---|---|---|
type number |
type number |
Negación |
type duration |
type duration |
Negación |
null |
null |
Para otros valores, se genera un error con el código de motivo "Expression.Error"
.
El operador unario menos se usa para cambiar el signo de un número o de una duración. Por ejemplo:
- (1 + 1) // -2
- - 1 // 1
- - - 1 // -1
- #nan // #nan
- #infinity // -#infinity
- #duration(1,0,0,0) // #duration(-1,0,0,0)
- #duration(0,1,30,0) // #duration(0,-1,-30,0)
Al evaluar el operador unario menos -x
, sucede lo siguiente:
Se propagan los errores que se producen al evaluar x
.
Si la expresión es un número, el resultado es el valor numérico de la expresión x
con el signo cambiado. Si el valor es NaN, el resultado también es NaN.
El operador de negación lógica (not
) se define para los tipos de valores siguientes:
X | Resultado | Interpretación |
---|---|---|
type logical |
type logical |
Negación |
null |
null |
Este operador calcula la operación not
lógica en un valor lógico determinado. Por ejemplo:
not true // false
not false // true
not (true and true) // false
Al evaluar el operador de negación lógica not x
, sucede lo siguiente:
Se propagan los errores que se producen al evaluar x
.
El valor generado de la evaluación de la expresión x debe ser un valor lógico, o bien se debe generar un error con el código de motivo "Expression.Error"
. Si el valor es true
, el resultado es false
. Si el operando es false
, el resultado es true
.
El resultado es un valor lógico.
Los operadores is
y as
se conocen como operadores de tipo.
El operador de compatibilidad de tipos x is y
se define para los tipos de valores siguientes:
X | Y | Resultado |
---|---|---|
type any |
nullable-primitive-type | type logical |
La expresión x is y
devuelve true
si el tipo asignado de x
es compatible con y
y devuelve false
si el tipo asignado de x
es incompatible con y
. y
debe ser nullable-primitivetype.
is-expression:
as-expression
is-expression is
nullable-primitive-type
nullable-primitive-type:
nullable
opt primitive-type
La compatibilidad de tipos, tal como la admite el operador is
, es un subconjunto de la compatibilidad con tipos generales y se define mediante las reglas siguientes:
Si x
es NULL, es compatible si y
es el tipo any
, el tipo null
o el tipo que acepta valores NULL.
Si x
no es NULL, es compatible si el tipo primitivo de x
es igual que y
.
Cuando se evalúa la expresión x is y
sucede lo siguiente:
x
.El operador de aserción de tipos x as y
se define para los tipos de valores siguientes:
X | Y | Resultado |
---|---|---|
type any |
nullable-primitive-type | type any |
La expresión x as y
afirma que el valor x
es compatible con y
según el operador is
. Si no es compatible, se produce un error. y
debe ser nullable-primitive-type.
as-expression:
equality-expression
as-expression as
nullable-primitive-type
La expresión x as y
se evalúa de esta forma:
Se realiza una comprobación de compatibilidad de tipos x is y
y la aserción devuelve x
sin modificar si la prueba se realiza correctamente.
Si se produce un error en la comprobación de compatibilidad, se genera un error con el código de motivo "Expression.Error"
.
Ejemplos:
1 as number // 1
"A" as number // error
null as nullable number // null
Cuando se evalúa la expresión x as y
sucede lo siguiente:
x
.El operador de fusión ??
devuelve el resultado de su operando izquierdo si no es NULL; de lo contrario, devolverá el resultado de su operando derecho. El operando derecho solamente se evalúa si el operando izquierdo no es NULL.
Cursos
Módulo
Realización de operaciones básicas con números en C# - Training
Conozca los operadores y las técnicas que se usan para realizar operaciones matemáticas básicas en datos numéricos.
Documentación
Valores del lenguaje M - PowerQuery M
Se describe el uso de valores en el lenguaje de fórmulas M de Power Query.
Funciones del lenguaje M - PowerQuery M
Se describe el uso de funciones en el lenguaje de fórmulas M de Power Query.
Tipos del lenguaje M - PowerQuery M
Se describe el uso de tipos en el lenguaje de fórmulas M de Power Query.