$str = '1s2.2s2.3p6.(3D).5d';
$parts = explode('.', $str);
foreach($parts as $key => $part) {
$part = preg_replace('/(\d[a-z])(\d)/i', '$1<sup>$2</sup>', $part);
$part = preg_replace('/\((\d)(.*)\)/', '(<sup>$1</sup>$2)', $part);
$parts[$key] = $part;
}
$out = implode($parts);
// 1s<sup>2</sup>2s<sup>2</sup>3p<sup>6</sup>(<sup>3</sup>D)5d
<?php
$result = preg_replace_callback('/(<[^>]+>)(\d+)(<[^>]+>)/', function($matches) { return $matches[1] . ($matches[2] - 120) . $matches[3]; } , '<*x>828<*/x> <*x>120<*/x> <*x>5<*/x>');
var_dump($result);
string(37) "<*x>708<*/x> <*x>0<*/x> <*x>-115<*/x>"