Funciones de math — referencia de Marketing Cloud AMPscript
La superficie de math de AMPscript — seis funciones, sin operadores, coerción silenciosa de string a número. El comportamiento de divide-por-cero cambia entre tenants, el math de plata tiene trampas de floating point, y 'abc' se vuelve 0 sin warning. Los patrones que sobreviven a escala.
La superficie de math de AMPscript es la más chica del catálogo: seis funciones para aritmética más Round para control de precisión. No hay operadores — no hay +, -, *, /. Cada operación aritmética es una llamada a función: Add(@a, @b), Multiply(@price, @qty). Los inputs se coercen de string a número en el momento de la llamada, en silencio — Add("three", 5) devuelve 5 en vez de tirar. La lista abajo es la superficie más las formas de falla que solo encontrás en producción.
Sintaxis oficial
%%[
/* Aritmética básica — cada operación es una función */
SET @sum = Add(@price, @shipping)
SET @diff = Subtract(@total, @discount)
SET @prod = Multiply(@unitPrice, @qty)
SET @quot = Divide(@total, @taxRate) /* ver trampa de divide-por-cero abajo */
/* Modulo — útil para personalización alternante */
SET @bucket = Mod(@subscriberId, 4)
/* 0, 1, 2, 3 — elegí una variante de contenido por destinatario */
/* Redondeo */
SET @rounded = Round(@price, 2) /* 2 decimales */
SET @whole = Round(@price) /* entero más cercano cuando se omite el arg */
/* Llamadas anidadas — legible para expresiones cortas */
SET @grandTotal = Add(Multiply(@price, @qty), @shipping)
/* Para expresiones largas, armá con variables intermedias nombradas */
SET @subtotal = Multiply(@price, @qty)
SET @afterTax = Multiply(@subtotal, Add(1, @taxRate))
SET @final = Subtract(@afterTax, @discount)
]%%El set soportado:
| Función | Qué hace | Notas |
|---|---|---|
| Add(a, b) | a + b | Variádico en algunos tenants (Add(a, b, c)); usá la forma binaria para portabilidad |
| Subtract(a, b) | a - b | El orden importa; no hay función de negación unaria |
| Multiply(a, b) | a * b | |
| Divide(a, b) | a / b | El comportamiento de divide-por-cero depende del tenant — guardalo explícito |
| Mod(a, b) | Resto de a / b | Útil para contenido alternante "cada N-ésimo destinatario" |
| Round(n [, digits]) | Redondear a digits decimales | Omitir digits redondea a entero; modo de redondeo es banker's rounding (lejos de cero en .5) |
Referencia:
- AMPscript Guide — referencia de funciones (sección math) ↗
- Salesforce Developer — funciones AMPscript ↗
Lo que sobrevive en producción
La coerción string-a-número es silenciosa — un input malo se vuelve 0
AMPscript coercea cada input de math desde su representación de string a un número en el momento de la llamada a la función. Si el input no parsea como número, la función usa 0 y devuelve un resultado equivocado sin quejarse.
%%[
/* "3" + "4" → 7. Coerción estándar. */
SET @a = Add("3", "4") /* → 7 */
/* "abc" + 5 → 5. El "abc" coerceado a 0, después 0 + 5 = 5. */
SET @b = Add("abc", 5) /* → 5 — silenciosamente mal */
/* "1.000" + 5 → 5. El punto rompe el parse en formato US. */
SET @c = Add("1,000", 5) /* → 5 — la coma falla el parse, se vuelve 0 */
/* NULL + 5 → 5. NULL coerceado a 0. */
SET @d = Add(NULL, 5) /* → 5 */
]%%Defensa: validá antes del math. Si el input vino de un Lookup o AttributeValue, chequeá Empty() primero y defaulteá. Si el input tiene formato (comas, símbolos de moneda), stripealos con Replace antes de pasarlo a una función de math:
%%[
SET @raw = AttributeValue("CustomerLifetimeValue") /* puede ser "$1,234.50" */
SET @clean = Replace(Replace(@raw, "$", ""), ",", "")
SET @value = Add(@clean, 0) /* coercer a número */
IF Empty(@raw) THEN
SET @value = 0
ENDIF
]%%El comportamiento de divide-por-cero depende del tenant — guardalo explícito
Divide(a, 0) devuelve 0 en algunos tenants y tira un error de runtime en otros. El comportamiento cambió entre ediciones de SFMC y no está garantizado hacia adelante.
%%[
/* EN RIESGO — según el tenant, esto devuelve 0 o tira error */
SET @rate = Divide(@conversions, @impressions)
/* DURABLE — guardalo antes de dividir */
IF @impressions == 0 OR Empty(@impressions) THEN
SET @rate = 0
ELSE
SET @rate = Divide(@conversions, @impressions)
ENDIF
]%%La falla del hand-off: un email testeado en dev con @impressions = 1000 sale, corre contra un destinatario donde @impressions = 0, y o renderea 0 (personalización silenciosamente mal) o falla el paso de la Send Activity (ruidoso pero raro). Guardá cada Divide donde el denominador podría ser cero, NULL, o no-numérico.
Precisión de floating-point: el math de plata no es seguro a escala
AMPscript usa aritmética de floating-point (.NET doubles por debajo). Los problemas clásicos de precisión de floating-point aplican: Add(0.1, 0.2) puede no ser exactamente 0.3, y cálculos de moneda a lo largo de muchas operaciones acumulan error.
%%[
SET @cents = Multiply(@amount, 100)
SET @rounded = Round(@cents, 0) /* redondear a centavos enteros */
SET @final = Divide(@rounded, 100) /* volver a dólares */
/* Final ahora es preciso a 2 decimales — sin cola de floating-point */
/* El approach ingenuo pierde precisión a lo largo de muchas operaciones */
SET @bad = Add(Multiply(@price, 0.07), @price)
/* Para algunos precios, @bad tiene dígitos al final como 19.450000000001 */
]%%La regla Cleon: hacé math de plata en centavos (enteros), no en dólares. Multiplicá por 100 al inicio, trabajá en centavos, dividí por 100 solo en el paso de display. Para contextos de alta precisión (math de impuestos, reconciliación multi-moneda), hacé el math en una SQL Activity que use DECIMAL(18,4) y pasá el resultado como una columna pre-computada a AMPscript.
Mod para personalización "cada N-ésimo destinatario"
Mod es el caballo de batalla subutilizado para personalización alternante sin una columna upstream. Apareadlo con un valor por destinatario estable y con forma de entero (un hash del SubscriberKey, un ID-mod-N pre-computado en SQL, etc.) y podés ramificar sobre 0/1/2 para variar el cuerpo del email.
%%[
SET @subId = AttributeValue("SubscriberKey")
/* SubscriberKey es un string; coercealo a número donde se pueda.
Mejor: pre-computá SubscriberKey % 4 en una columna upstream. */
SET @bucket = Mod(@subId, 4)
IF @bucket == 0 THEN
SET @heroImage = "hero-a.jpg"
ELSEIF @bucket == 1 THEN
SET @heroImage = "hero-b.jpg"
ELSEIF @bucket == 2 THEN
SET @heroImage = "hero-c.jpg"
ELSE
SET @heroImage = "hero-d.jpg"
ENDIF
]%%Un SubscriberKey que es un UUID o un string no-numérico se coercea a 0 (ver la trampa de coerción silenciosa), y cada destinatario aterriza en el bucket 0. Si tu audiencia tiene IDs no-numéricos, pre-computá el bucket en SQL upstream y leelo como una columna.
Round usa banker's rounding por default
Round(0.5) devuelve 0 en AMPscript en algunos tenants (banker's rounding redondea a par), 1 en otros (half-up rounding). La diferencia es chica por fila pero se acumula a lo largo de una audiencia.
%%[
SET @a = Round(0.5) /* depende del tenant: 0 o 1 */
SET @b = Round(1.5) /* depende del tenant: 2 (ambos modos) */
SET @c = Round(2.5) /* depende del tenant: 2 (banker's) o 3 (half-up) */
]%%Cuando el comportamiento de redondeo importa para corrección legal / contable (precios con impuestos incluidos, porcentajes que tienen que sumar exactamente 100%), no redondees en AMPscript. Pre-computá en SQL donde podés elegir la función de redondeo explícitamente (ROUND vs FLOOR vs CEILING).
Las llamadas anidadas hieren la legibilidad pasando 3 niveles
La sintaxis de llamada a función de AMPscript para math se banca para expresiones cortas y duele para las largas. El punto de quiebre es alrededor de tres llamadas anidadas — más allá de eso, las variables intermedias nombradas se leen mejor.
%%[
/* OK — lo suficientemente corto */
SET @x = Add(Multiply(@price, @qty), @shipping)
/* DOLOROSO — intentá parsear el orden de operaciones de un vistazo */
SET @y = Divide(Subtract(Multiply(@price, @qty), @discount), Add(1, @taxRate))
/* MEJOR — nombrá los intermedios, comentá la fórmula */
/* y = (price * qty - discount) / (1 + taxRate) */
SET @subtotal = Multiply(@price, @qty)
SET @afterDisc = Subtract(@subtotal, @discount)
SET @taxFactor = Add(1, @taxRate)
SET @y = Divide(@afterDisc, @taxFactor)
]%%La falla del hand-off no es un bug — es que la próxima persona cambiando la fórmula tiene que mentalmente parsear los paréntesis y el orden de operaciones. Seis meses después introducen un error aritmético porque la expresión original era ilegible.
Decisión rápida
Usá Add / Subtract / Multiply / Divide cuando:
- La aritmética es corta (1-3 operaciones) y los inputs están validados.
Usá Mod cuando:
- Necesitás contenido alternante por destinatario y tenés un ID numérico estable. Pre-computá el bucket upstream si los IDs no son numéricos.
Usá Round cuando:
- El output va a un subscriber y la precisión decimal importa para display. Confirmá el modo de redondeo si se necesita precisión de nivel contable.
Usá variables intermedias nombradas cuando:
- La fórmula tiene 4+ operaciones o más de 2 niveles de anidado. La legibilidad previene el próximo bug de hand-off.
Hacé el math en SQL en su lugar cuando:
- Aritmética de plata o impuestos donde la precisión importa (el patrón centavos-como-entero en SQL es más limpio que el workaround AMPscript).
- El mismo cálculo corre para cada destinatario en un send grande.
- Necesitás potencia, raíz cuadrada, o cualquier función de math que AMPscript no trae.
- El modo de redondeo importa y necesitás control explícito (
FLOOR,CEILING, banker's vs half-up).
Relacionado
- Basics — superficie del lenguaje soportada
- Funciones de string —
FormatNumberpara mostrar resultados numéricos con formateo de locale - Funciones de fecha — la aritmética de fechas usa
DateAdd/DateDiff, no estas funciones de math - Gotchas de MC AMPscript — ver #6 (comparaciones de tipos sueltos; la misma trampa aplica al math al comparar resultados)
- MC SQL — funciones numéricas — el upstream donde el math pesado debería pasar
Más páginas de referencia AMPscript en camino: Validación · Data Extension · Subscriber/Profile · Cloud-write · Encoding/Hashing · Style Guide.