Почему toPrecision возвращает строку? - PullRequest
2 голосов
/ 02 февраля 2009

Посмотреть этот код:

function testprecision(){
    var isNotNumber = parseFloat('1.3').toPrecision(6);
    alert(typeof isNotNumber); //=> string
}

Я бы ожидал число. Если 'isNotNumber' должен быть действительным числом, решение проблемы заключается в переопределении:

alert(typeof parseFloat(isNotNumber)) //=> number

[Изменить] спасибо за ваши ответы. Точность не очень точный термин, который я заключаю. Он может представлять общее количество цифр числа или число дробных цифр . Большинство людей в Нидерландах (откуда я родом) думают о точности в «количестве дробных цифр». Метод javascript toPrecision касается первого представления, поэтому это сбивает с толку. В любом случае, метод позволяет ввести «ложную точность», я прав? Для второго значения, которое мы должны исправить, то же самое относится и к этому (возвращает строку, возможность ложной точности).

Как бы то ни было, сделав изобретать велосипед своим главным хобби, я начал играть, создавая объект плавания javascript, используя полученные здесь знания. Может быть, это кому-то пригодится, или у кого-то из вас есть идеи получше?

function Float(f,nDec) {
  var Base = this,val;
  setPrecision( nDec || 2 );      
  set( f || 0, nDec || Base.precision );
  Base.set    = set;
  Base.ndec   = setPrecision;
  /** public setprecision 
   *  sets a value for the number of fractional
   *  digits (decimals) you would like getf to 
   *  return. NB: can't be more than 20.
   *  Returns the Float object, so allows method 
   *  chaining
   *  @param {Number} iPrecision
   */
  function setPrecision(iPrecision) {
      var ix = parseInt(iPrecision,10) || 2;
       Base.precision = ix >= 21 ? 20 : ix;
       return Base;
  }
  /** public set
   *  sets the 'internal' value of the object. Returns
   *  the Float object, so allows method chaining
   *  @param {Number} f
   *  @param {Number} ndec
   */
  function set(f,ndec) {
       val =  parseFloat(f) || 0;
       if (ndec) { setPrecision(ndec); }
       Base.val = val;
       return Base;
  }
  /** public get: 
   * return number value (as a float)
   */
  Base.get = function(){
      var ndec = Math.pow(10,Base.precision),
          ival = parseInt(val*ndec,10)/ndec;
      Base.val = ival;
      return Base.val;
  };
  /** public getf 
   *  returns formatted string with precision
   *  (see Base.setPrecision)
   *  if [hx] is supplied, it returns
   *  the float as hexadecimal, otherwise
   *  @param {Boolean} hx
   */
  Base.getf = function(hx){
      var v = Base.val.toFixed(Base.precision);
      return hx ? v.toString(16) : v;
  };
  /** public add
   * adds [f] to the current value (if [f] is a
   * Float, otherwise returns current value)
   * optionally sets a new number of decimals
   * from parameter [ndec]
   * @param {Number} f
   * @param {Number} ndec
   */
  Base.add = function(f,ndec){
      if ( parseFloat(f) || val===0) {
           set(Base.val+parseFloat(f));
           if (ndec) { setPrecision(ndec);}
      }
     return Base.get();
  };
  /** toString 
   *  returns the internal value of the Float object
   *  functions like a getter (supposedly)
   */
  Base.toString = Base.get;
}

использование / пример:

var xf = new Float(); //=> value now 0.0
xf.set(0.86/0.8765,17).add(3.459);
alert(xf+'|'+xf.getf()); //=> 4.440175128351398|4.44017512835139800

Ответы [ 6 ]

10 голосов
/ 02 февраля 2009

Предположим, у вас есть число, подобное '1.6'. Если вы отформатируете его так, чтобы справа было 6 нулей, вы получите «1.600000». Для компьютера это все тот же номер, что и для 1.6, но для вас и вашего веб-сайта это не то же самое, если все ваши числа имеют разную длину (например, это может повредить анализатору).

Так, чтобы избежать этого, toPrecision возвращает строку, иначе интерпретатор переформатировал бы число, чтобы снова стать '1.6'.

10 голосов
/ 02 февраля 2009

Из документов: «Возвращает строку, представляющую объект Number с заданной точностью.»

toPrecision (), похоже, предназначен для форматирования вывода, и в этом случае строка является наиболее разумным результатом. Он представляет окончательный результат в форме, которая не будет искажена в результате дальнейших манипуляций.

Если вы хотите выполнить некоторое усечение точности по причинам, связанным с вычислениями, я стремлюсь умножить на 10 ^ n, где n - это цифры, которые я хочу сохранить, взять из них целое число и затем снова разделить на то же. Это не идеально: в некоторых ситуациях вы можете вызвать переполнение. Честно говоря, я предпочитаю делать более сложные финансовые расчеты на сервере, где у меня есть валюта, двоично-десятичное или аналогичные числовые типы.

5 голосов
/ 11 декабря 2010

Цель toPrecision - усечь значащие десятичные цифры Number до указанного количества. Но тип данных внутренних представлений Number s является двоичным IEEE-754 double. Поэтому невозможно сохранить точное значение в большинстве случаев Number. В результате этой неточности возвращаемое значение будет иметь бесконечное количество десятичных цифр, что сделает toPrecision недействительным.

Таким образом, единственное разумное решение этой проблемы - вернуть десятичные цифры. И в настоящее время единственным разумным типом данных JS для десятичных цифр является строка.


Вот пример, поясняющий неточность Number с, если используется для десятичных цифр:

// the following looks like something with 2 decimal digits:
var number = 1.6;

// but in fact it's a number with an infinite amount of decimal digits.
// let's look at the first 30 of them:
alert(number.toPrecision(30));

// 1.60000000000000008881784197001
3 голосов
/ 02 февраля 2009

Потому что это функция форматирования.

1 голос
/ 02 февраля 2009

Вам нужна строка для конечных нулей. Хороший пример - отображение валюты.

0 голосов
/ 02 февраля 2009

Проблема в использовании toPrecision. Попробуйте без.

var isNotNumber = parseFloat('1.3');
alert(typeof isNotNumber); //=> number
...