Вы упоминаете, что некоторые случаи не работают, и вы не знаете, почему.Я думаю, что это связано с вашими if-утверждениями.
Например, первый, если в первом цикле:
if (!(s1.charAt(i) == 0 || s2.charAt(i) == 0)) {...}
будет оценивать значение true в тех же самых случаях, что и остальные, если за ним следует:
else if (s1.charAt(i) != 0 && s2.charAt(i) != 0) {...}
(Потому что в первом случае вы сначала оцениваете, равно ли какое-либо значение нулю, а затем инвертируете результат).
А затем первый вложенный элемент в первом цикле:
if ((int) (s1.charAt(i)) + (int) (s2.charAt(i)) - 96 < 10) {...}
Мне кажетсяэто всегда будет иметь значение true, потому что вы берете один символ из обеих строк.Таким образом, наивысший возможный результат от добавления - 18. Вычтите 96 из этого, и оно должно быть меньше 10.
Чтобы отладить это и найти проблему, я бы рекомендовал начать с двойной проверки всехоператоры if.Запишите в комментариях или даже сделайте диаграмму, чтобы определить, когда должен быть достигнут определенный шаг и что должно произойти там.Кроме того, если вы еще не используете интегрированную среду разработки, которая может помочь, поскольку она предупредит вас о некоторых проблемах в логике.