2016-10-15 16 views
0

Math.sin() Различная точность между Node.js и C#

У меня проблема с точностью в последней цифре после запятой. Код javascript генерирует один меньше Digit по сравнению с кодом C#.

Вот простой Node.js код

var seed = 45; 
var x = Math.sin(seed) * 0.5; 
console.log(x);//0.4254517622670592 

Вот простой C# код

public String pseudorandom() 
{ 
    int seed = 45; 
    double num = Math.Sin(seed) * (0.5); 
    return num.ToString("G15");//0.42545176226705922 
} 

Как достичь того же точность?

+1

Вы сравниваете результаты двух языков, преобразуя числовую форму в строку. Чего вы действительно пытаетесь достичь? Что именно является источником вашего интереса к «точности»? Оба языка используют собственную плавающую точку IEEE 754. – Pointy

+0

Я пытаюсь достичь той же точности. Я не могу понять ваш отрицательный голос. – PrOgrAMmer

+0

Я не спускал вниз; Я просто пытаюсь понять, что вы пытаетесь сделать. Вы печатаете числовое значение, которое в обоих случаях включает преобразование значения в строку, чтобы оно можно было распечатать.Нет никакой гарантии, что правила обоих языков для этого одинаковы. – Pointy

ответ

2

Тип JavaScript Number довольно сложный. Похоже, что число с плавающей запятой, вероятно, будет похоже на IEEE 754-2008, но некоторые аспекты остаются в реализации. См. http://www.ecma-international.org/ecma-262/6.0/#sec-number-objects с 12.7.

Существует примечанию

Выход toFixed может быть более точным, чем ToString для некоторых значений, потому что ToString печатает только количество значащих цифр, чтобы отличить число от соседних числовых значений. Например,

(1000000000000000128).toString() возвращает «1000000000000000100», а (1000000000000000128).toFixed(0) возвращает «1000000000000000128».

Таким образом, чтобы получить полную точность цифр вам нужно что-то вроде

seed = 45; 
x = Math.sin(seed) * 0.5; 
x.toFixed(17); 
// on my platform its "0.42545176226705922" 

Кроме того, обратите внимание на спецификацию как реализация греха и потому позволяют некоторое разнообразие в существующем алгоритме. Это гарантируется только в пределах +/- 1 ULP.

Использование java Алгоритм печати отличается. Даже форсирование 17 цифр дает результат как 0,42545176226705920.

Вы можете проверить, что вы получаете одинаковые битовые шаблоны, используя x.toString(2) и Double.doubleToLongBits(x) в Java.

2
return num.ToString("G15");//0.42545176226705922 

фактически возвращает «+0,425451762267059» (не значащей цифры + 15 знаков после запятой в данном примере), а не точность, показанную в комментарии после.

Таким образом, вы будете использовать:

return num.ToString("G16"); 

, чтобы получить "+0,4254517622670592"

(для примера - когда значимая цифра всегда 0) G16 будет 16 знаков после запятой.