Разделите два значения BigInt и приведите результат к Float в Scala - PullRequest
2 голосов
/ 12 февраля 2020

У меня есть фрейм данных, который содержит два столбца типа BigInt . Затем у меня есть пользовательская функция, которая выполняет операцию над этими двумя столбцами, и предполагается, что конечный результат будет иметь тип Float .

def generateNewColumnValue(firstColumnValue: BigInt, secondColumnValue: BigInt): Float = {
   val calculated = scala.math.pow(firstColumnValue.toFloat / secondColumnValue, 1.0/3.0);
   return calculated;
}

val generateNewColumnValueUDF = udf[Float, BigInt, BigInt](generateNewColumnValue);

Внутри тела UDF Я делаю очень простые вычисления, как вы можете видеть. Проблема в том, что я получаю следующую ошибку, и я не понимаю, почему это невозможно:

command-836521033094408:9: error: overloaded method value / with alternatives:
  (x: Double)Double <and>
  (x: Float)Float <and>
  (x: Long)Float <and>
  (x: Int)Float <and>
  (x: Char)Float <and>
  (x: Short)Float <and>
  (x: Byte)Float
 cannot be applied to (BigInt)
  val calculated = scala.math.pow(firstColumnValue.toFloat / secondColumnValue, 1.0/3.0);

Проблема в том, что, если я пытаюсь привести его к типу с более низким диапазоном (например, Int), я может потерять некоторое значение после десятичной точки.

1 Ответ

2 голосов
/ 12 февраля 2020

В сообщении просто говорится, что вы можете разделить Float на Double, Float и т. Д. c. но не на BigInt. Вызовите toFloat для обоих операндов, а не только для одного:

firstColumnValue.toFloat / secondColumnValue.toFloat

Но math.pow занимает Double с, а не Float с, поэтому toDouble имеет больше смысла. Если результат должен быть Float, вызовите toFloat для результата pow, а не для его аргументов.

Или через BigDecimal:

(BigDecimal(firstColumnValue) / BigDecimal(secondColumnValue)).toDouble

В большинстве в случаях он должен давать примерно тот же результат, что и первый вариант, но медленнее; проблема в том, что BigInt s может быть настолько большим, что firstColumnValue.toDouble возвращает Double.PositiveInfinity / NegativeInfinity. Вы можете проверить это и использовать только второй вариант в этом случае.

...