Зачем такая большая потеря точности данных с "float" в Kotlin? - PullRequest
0 голосов
/ 11 января 2020

Я использую MPAndroidChart для построения графика в моем приложении Android. Функция "entry ()", которая принимает значение оси x и значение оси y, имеет синтаксис объявления как: entry (float x, float y)

Теперь моя проблема с Число с плавающей точкой в ​​Kotlin выглядит следующим образом:

Я продолжаю получать данные от другого устройства Bluetooth, в котором одно из полей данных является значением метки времени (32-разрядный без знака). Это значение отметки времени указывается в мс, мне нужно разделить это значение на 1000 и отобразить значения оси x в «se c». Однако я теряю большую точность с типом данных «float» в Kotlin.

Например, рассмотрим следующий код:

/**
* You can edit, run, and share this code. 
* play.kotlinlang.org 
*/

import java.text.DecimalFormat;

fun main() {
   var mArrayList:ArrayList<UByte> = ArrayList()
   mArrayList.add(0xFF.toUByte())
   mArrayList.add(0xFF.toUByte())
   mArrayList.add(0xFF.toUByte())
   mArrayList.add(0xFF.toUByte())


   var intInc:UByte = 0.toUByte()
   var mTimeStamp:UInt 
   var mFloatVal:Float 
   var mDoubleVal:Double 

   for(i in 1..10){
       mArrayList.set(3, intInc)
       intInc = intInc.plus(2.toUByte()).toUByte()

       mTimeStamp = mArrayList.get(0).toUInt().shl(24)
       mTimeStamp = mTimeStamp.or(mArrayList.get(1).toUInt().shl(16))
       mTimeStamp = mTimeStamp.or(mArrayList.get(2).toUInt().shl(8))
       mTimeStamp = mTimeStamp.or(mArrayList.get(3).toUInt().shl(0))

       mDoubleVal = mTimeStamp.toDouble()
       mDoubleVal = mDoubleVal.div(1000)
       mFloatVal = mDoubleVal.toFloat()
       println("mTimeSTamp = $mTimeStamp, mDoubleVal = $mDoubleVal, mFloatVal = $mFloatVal")
   }   
}

Вывод кода:

mTimeSTamp = 4294967040, mDoubleVal = 4294967.04, mFloatVal = 4294967.0
mTimeSTamp = 4294967042, mDoubleVal = 4294967.042, mFloatVal = 4294967.0
mTimeSTamp = 4294967044, mDoubleVal = 4294967.044, mFloatVal = 4294967.0
mTimeSTamp = 4294967046, mDoubleVal = 4294967.046, mFloatVal = 4294967.0
mTimeSTamp = 4294967048, mDoubleVal = 4294967.048, mFloatVal = 4294967.0
mTimeSTamp = 4294967050, mDoubleVal = 4294967.05, mFloatVal = 4294967.0
mTimeSTamp = 4294967052, mDoubleVal = 4294967.052, mFloatVal = 4294967.0
mTimeSTamp = 4294967054, mDoubleVal = 4294967.054, mFloatVal = 4294967.0
mTimeSTamp = 4294967056, mDoubleVal = 4294967.056, mFloatVal = 4294967.0
mTimeSTamp = 4294967058, mDoubleVal = 4294967.058, mFloatVal = 4294967.0

Сравнивая выше mDoubleVal и mFloatVal, кажется, что потеря точности данных слишком велика. Мне нужно точное значение с плавающей запятой до 3 десятичных знаков. Как мне этого добиться? Я понимаю, что мы не можем точно представлять числа с плавающей запятой из-за ограничений в представлении, но удивительно, что это ограничение начинается с первой десятичной запятой.

1 Ответ

1 голос
/ 12 января 2020

Вы не можете.

C / java / kotlin float - это число с плавающей запятой IEEE с одинарной точностью. Таким образом, вы получите 24 бита (23 хранимых бита мантиссы плюс неявный ведущий 1) или около 7 десятичных знаков точности. Когда вы используете больше цифр до десятичной точки, вы получаете меньше после десятичной точки.

...