2013-06-08 4 views
-3

Эта операция должна возвращать 2, но он возвращает 1 вместо из-за представления с плавающей запятой:значащих десятичные цифры (или 0,3 - 0,1 = 0,1)

a <- .3 
b <- .1 
floor((a-b)*10) 

Я в принципе хочет первую цифру после точки, фактического результата базы-10, а не результата компьютера с плавающей запятой. В этом случае a и b имеют только одну десятичную цифру, но в большинстве случаев их будет больше. Примеры:

  • 0.3-0.1=0.2 поэтому я хочу, чтобы 2
  • 0.5-0.001=0.499 поэтому я хочу, чтобы 4
  • 0.925-0.113=0.812 поэтому я хочу 8
  • 0.57-0.11=0.46 поэтому я хочу 4
  • 0.12-0.11=0.01 поэтому я хочу 0

То есть, не округление, но усечение. Я думал об использовании этого:

floor(floor((a-b)*100)/10) 

но я не уверен, что это лучшее, что я могу сделать.

обновление: действительно, он не работает (см комментарии ниже):

floor(floor((.9-.8)*100)/10) # gives 0 instead of 1 
floor(round((.5-.001)*100)/10) # gives 5 instead of 1 

обновление 2: думаю, что это действительно работает (по крайней мере, во всех случаях, перечисленных до сих пор):

substring(as.character(a-b),first=3,last=3) 

Предложения?

+0

когда вы хотите, чтобы значение округляется вверх, и когда вы хотите, чтобы не быть? Вам нужно лучше определить желаемое поведение. Например, что должно быть возвращено '.5 - .001' и как вы это отличаетесь от' .3 - .1'? –

+0

Это не округление, просто усечение. См. Примеры в отредактированном вопросе –

+0

Да, похоже, что это просто усекается, но из-за того, что хранится '.3 - .1', вам нужно округлить, чтобы получить' .2'. О, и попробуйте свою последнюю попытку на '1-.9' или' .9-.8'. Это сложнее, чем кажется. –

ответ

1

Это невозможно, потому что информации больше нет: Двойники не могут точно представлять десятичные числа.

Если у вас все в порядке с приблизительным решением, вы можете добавить небольшое количество и усечь результат. Например, если вы знаете, что ваши номера имеют в большинстве 14 цифр, следующий будет работать:

first_digit <- function(x, epsilon=5e-15) 
    floor((x+epsilon) * 10) 
first_digit(.3 - .1 ) # 2 
first_digit(.5 - .001) # 4 
first_digit(.925 - .113) # 8 
first_digit(.57 - .11 ) # 4 
first_digit(.12 - .11 ) # 0 

Если вы хотите первую значительной цифры (что означает «первую ненулевую цифру»), вы можете использовать:

first_significant_digit <- function(x, epsilon=5e-14) 
    floor((x+epsilon) * 10^-floor(log10(x+epsilon))) 
first_significant_digit(0.12-0.11) # 1 
+0

Да, это должно сработать. Все числа поступают из файла, в котором содержится не более 4 десятичных цифр. Вы думаете, что 'подстрока (as.character (a-b), first = 3, last = 3)' тоже будет работать? –

+2

Если у них не более 4 десятичных знаков, вы можете их загрузить, умножить на 1e4, округлить их, а затем преобразовать в целые числа. Тогда вам не придется иметь дело с ошибками с плавающей запятой. – flodel

Смежные вопросы